jQuery move Cursor Back "X" amount of Spaces - javascript

I need it so that when a button is pressed, the cursor will:
1) Locate the end of the sentence
2) Move the cursor back from the end of the sentence "x" many spaces (x is a variable);
Here's a fiddle -----> jsFiddle <------
HTML
<span>From the end, move the cursor back this many spaces: </span>
<input type='text' id='num' size='5'/>
<button>Submit</button>
<br/><br/>
<textarea>The cursor will move in here</textarea>
jQuery
$(document).ready(function() {
$('button').click(function() {
var myval = parseInt($('#num').val()); //the number of spaces to move back
//code to move cursor back - starting from the END OF THE STATEMENT
});
});

You'd do that like so :
$(document).ready(function() {
$('button').click(function() {
var el = $('textarea')[0],
myval = parseInt($('#num').val(), 10),
cur_pos = 0;
if (el.selectionStart) {
cur_pos = el.selectionStart;
} else if (document.selection) {
el.focus();
var r = document.selection.createRange();
if (r != null) {
var re = el.createTextRange(),
rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
cur_pos = rc.text.length;
}
}
if (el.setSelectionRange) {
el.focus();
el.setSelectionRange(cur_pos-myval, cur_pos-myval);
}
else if (el.createTextRange) {
var range = el.createTextRange();
range.collapse(true);
range.moveEnd('character', cur_pos-myval);
range.moveStart('character', cur_pos-myval);
range.select();
}
});
});
FIDDLE

Related

Create button onclick function to act as arrow keys do

I have this Java script function that acts as a back space. This works fine but now I want to create a button that goes back, and one that goes forward without deleting the text ( like the behavior of your arrow keys ) . Any help with this is greatly appreciated.
function setBack() {
document.getElementById('user').value =
document.getElementById('user').value.substring(0,
document.getElementById('user').value.length - 1);
}
<input id="user" type="text">
<button type="button" onclick="setBack();">backspace</button>
<button type="button" onclick="">back</button>
<button type="button" onclick="">forward</button>
No jQuery please Native Javascript only.
Give this a try:
let input = document.getElementById('Test');
input.focus();
let index = 0;
document.getElementById('Prev').addEventListener('click', function(){
index -= 1;
if(index <= 0) {
index = input.value.length;
}
input.focus();
input.selectionEnd = index;
input.selectionStart = index;
});
document.getElementById('Next').addEventListener('click', function(){
console.log(index);
index += 1;
if(index > input.value.length) {
index = 0;
}
input.focus();
input.selectionEnd = index;
input.selectionStart = index;
});
<input id="Test" type="text" value="helloooo">
<button id="Prev">Prev</button>
<button id="Next">Next</button>
You can do that by obtaining the cursor location which is possible with selectionStart. Here is the sample code. You can add more features to this as per the requirement.
function back(){
console.log(user.selectionStart-1)
if(user.selectionStart !== 0 ){
user.focus();
user.selectionEnd = user.selectionStart
user.selectionStart = user.selectionStart-1
}
}
function forward(){
console.log(user.selectionStart)
user.focus()
user.selectionEnd = user.selectionStart+1
user.selectionStart = user.selectionStart+1
}
You can store caret position inside var say caretPosition . And pass caret position after back and forward. Just increment pos on forward and decrement pos on back. here is how i have tried.
var caretPosition = 0;
function updateLength(){
caretPosition = document.getElementById('user').value.length
}
function setBack(e) {
var str= document.getElementById('user').value;
var position =document.getElementById('user').selectionStart;
caretPosition = position-1;
document.getElementById('user').value =
str.substring(0,position - 1) + str.substring(position, str.length)
resetCaretPosition('user',caretPosition);
}
function back(){
caretPosition =(caretPosition>1)?caretPosition-1:caretPosition ;
resetCaretPosition('user',caretPosition);
}
function forward(){
caretPosition =caretPosition+1 ;
resetCaretPosition('user',caretPosition);
}
function resetCaretPosition(elemId, caretPos){
var elem = document.getElementById(elemId);
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
}
}
<input id="user" oninput="updateLength()" type="text">
<button type="button" onclick="setBack(event);">backspace</button>
<button type="button" onclick="back()">back</button>
<button type="button" onclick="forward()">forward</button>

how to get the correct caret position

I'm making a contenteditable based input and I want to add emoticon support
i have the contenteditable div, and inside is only text and IMG_TAG for emoticons. On blur, I want to save the caret position. And when I click to open the emoticon box to focus the contenteditable and set the caret where it was. Something to simulate web.whatsapp.com behaviour
I've found this piece of code
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ((sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
But it does not give me the correct position.
"hello IMG_TAG john". If the cursor is just before the IMG_TAG -> the position is 6, which is correct, but if it is just after the IMG_TAG is still 6.
Also, I didn't find a good "setCaretPosition" function to work well for me.
I've been searching for two hours now. Anyone got a good answer ?
In the demo we have used the Selection and Range APIs for for setting and gettingšŸ—” the caret's position. Since the OP needs to find a caret's position, we will concentrate on the getCaret() function:
var btn2 = document.getElementById('btn2');
btn2.addEventListener('click', getCaret, false);
function getCaret() {
var sel = window.getSelection();
var end = sel.focusOffset;
var out1 = document.getElementById('out1');
out1.textContent = end;
}
The function references the Selection object
Then you store the Selection object's property, focusOffset
focusOffset will give us an integer representing the number of characters there are between it (focusNode) and the beginning of the Selection (anchorNode). If the Selection contains an element, then it includes the element's childNodes into the count as well.
When testing the getCaret() function, just select some text, then click the Get Focus button, the result is displayed next to the area labeled Caret Position:
SNIPPET
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<style>
fieldset {
margin: 20px auto;
}
input {
width: 5ex;
text-align: center;
padding: 1px 3px;
}
</style>
</head>
<body>
<div id="editor1" contenteditable="true">
<br/>123456789abcdefghijklmnopqrstuvwxyz
<br/>12 45678 abcd fg ijk mnopqrst vwxyz
<br/>123 5 789a cde ghijklm o qrst v xyz
<br/>12345 789abcd fg ijklmnopq s u wxyz
<br/>123 567 9abc efg ijklm op rst vwxy
<br/>1 34 6789a cdef hij lm opq stuvwxyz
<br/>1 3456 89a cd fghij l no qrst vwx z
<br/>12 4 6789 bcd fgh j lmno q stuv xy
</div>
<fieldset>
<input type="button" class="fontStyle" onclick="document.execCommand('italic',false,null);" value="I" title="Italicize Highlighted Text">
<input type="button" class="fontStyle" onclick="document.execCommand('bold',false,null);" value="B" title="Bold Highlighted Text">
<input id="row" name="row" placeholder="Row#" />
<input id="col" name="col" placeholder="Col#" />
<button id="btn1">Set Focus</button>
<button id="btn2">Get Focus</button>
<label for='out1'>Caret Position:</label>
<output id="out1"></output>
</fieldset>
<p>Each row has a number of non-repeated string of alphanumeric characters:</p>
<pre><code>123456789abcdefghijklmnopqrstuvwxyz</code></pre>
<p>Maximum of 35 characters. Every row except the first row has some missing characters and in their place is a whitespace.
</p>
<script>
function setCaret(x, y) {
var ele = document.getElementById("editor1");
var rng = document.createRange();
var sel = window.getSelection();
var row = parseInt(x, 10) * 2;
var col = parseInt(y, 10);
rng.setStart(ele.childNodes[row], col);
rng.collapse(true);
sel.removeAllRanges();
sel.addRange(rng);
ele.focus();
}
function getCaret() {
var sel = window.getSelection();
var end = sel.focusOffset;
var out1 = document.getElementById('out1');
out1.textContent = end;
}
var btn2 = document.getElementById('btn2');
var btn1 = document.getElementById('btn1');
btn1.addEventListener('click', function(event) {
var rowSet = document.getElementById('row').value;
var colSet = document.getElementById('col').value;
setCaret(rowSet, colSet);
}, true);
btn2.addEventListener('click', getCaret, false);
</script>
</body>
</html>
šŸ—”Just figured it out after trying to remember how setCaret() function worked.

Get and set cursor position with contenteditable div

I have a contenteditable div which I would like to be able to have users insert things such as links, images or YouTube videos. At the moment this is what I have:
function addLink() {
var link = $('#url').val();
$('#editor').focus();
document.execCommand('createLink', false, link);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Text Editor -->
<div id="editor" contenteditable="true"></div>
<!-- Add Link -->
<input type="text" id="url">
<button onclick="addLink()">Submit</button>
As you can see, the user has to type into a separate text box to enter the link address. As a result, when the link is added to the editor, it is not added to the position that the pointer/caret was on.
My question is how I can get and set the location of the pointer/caret. I have seen other questions such as this for setting the pointer however I would prefer to have a solution which is supported in all modern browsers, including Chrome, Safari, Firefox and IE9+.
Any ideas? Thanks.
Edit:
I found the code below which gets the position however, it only gets the position according to the line it is on. For example if I had this (where | is the cursor):
This is some text
And som|e more text
Then I would be returned the value 7, not 24.
function getPosition() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt) {
return sel.getRangeAt(0).startOffset;
}
}
return null;
}
There's a ton of related info onsite. This one works for me and my clients.
DEMO
https://stackoverflow.com/a/6249440/2813224
function setCaret(line, col) {
var ele = document.getElementById("editable");
var rng = document.createRange();
var sel = window.getSelection();
rng.setStart(ele.childNodes[line], col);
rng.collapse(true);
sel.removeAllRanges();
sel.addRange(rng);
ele.focus();
}
//https://stackoverflow.com/a/6249440/2813224
var line = document.getElementById('ln').value;
var col = document.getElementById('cl').value;
var btn = document.getElementById('btn');
btn.addEventListener('click', function(event) {
var lineSet = parseInt(line, 10);
var colSet = parseInt(col, 10);
setCaret(lineSet, colSet);
}, true);
<div id="editable" contenteditable="true">
<br/>text text text text text text
<br/>text text text text text text
<br/>text text text text text text
<br/>
<br/>
</div>
<fieldset>
<button id="btn">focus</button>
<input type="button" class="fontStyle" onclick="document.execCommand('italic',false,null);" value="I" title="Italicize Highlighted Text">
<input type="button" class="fontStyle" onclick="document.execCommand('bold',false,null);" value="B" title="Bold Highlighted Text">
<input id="ln" placeholder="Line#" />
<input id="cl" placeholder="Column#" />
</fieldset>
A good rich-text editor is one of the harder things to do currently, and is pretty much a project by itself (unfriendly API, huge number of corner cases, cross-browser differences, the list goes on). I would strongly advise you to try and find an existing solution.
Some libraries that can be used include:
Quill (http://quilljs.com)
WYSGIHTML (http://wysihtml.com)
CodeMirror library (http://codemirror.net)
I have tried to find a solution,
With a little help it can be perfected.
It is a combination of answers I've found on SO, and my exp.
Its tricky, its messy... but if you must, you can use it but it requires a bit of work to support inner links (if you cursor is on an anchor it will create anchor inside anchor)
Here's the JS:
var lastPos;
var curNode = 0;
function setCaret() {
curNode=0;
var el = document.getElementById("editor");
var range = document.createRange();
var sel = window.getSelection();
console.log(el.childNodes);
if (el.childNodes.length > 0) {
while (lastPos > el.childNodes[curNode].childNodes[0].textContent.length) {
lastPos = lastPos - el.childNodes[curNode].childNodes[0].textContent.length;
curNode++;
}
range.setStart(el.childNodes[curNode].childNodes[0], lastPos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
el.focus();
};
function savePos() {
lastPos = getCaretCharacterOffsetWithin(document.getElementById('editor'));
}
function addLink() {
console.log(lastPos);
setCaret();
console.log(getCaretCharacterOffsetWithin(document.getElementById('editor')));
console.log('focus');
// $("#editor").focus();
var link = $('#url').val();
document.execCommand('createLink', false, link);
}
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ((sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
fiddle
This is what you asked for, in your bounty: on the following example you can see how to detect the exact number of characters of the actual point where you clicked the mouse on:
<!-- Text Editor -->
<div id="editor" class="divClass" contenteditable="true">type here some text</div>
<script>
document.getElementById("editor").addEventListener("mouseup", function(key) {
alert(getCaretCharacterOffsetWithin(document.getElementById("editor")));
}, false);
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
</script>
I found a problem with emojis. Emojis have a length which is more than 1.
I solved it.
<script>
function getCursorPosition() {
if(window.getSelection()){
var sel = window.getSelection();
if(sel.getRangeAt){
var pos = sel.getRangeAt(0).startOffset;
var endPos = pos + Array.from(editor.innerHTML.slice(0,pos)).length - editor.innerHTML.slice(0,pos).split("").length;
return endPos;
}
}
return null;
}
var editor = document.querySelector("#editor");
var output = document.querySelector("#output");
editor.addEventListener("input",function(){
output.innerHTML = "Selection: " + getCursorPosition();
});
</script>
<div contenteditable id="editor">text</div>
<div id="output">Selection:</div>

Set cursor within text of input using jQuery

Using this topic:
jQuery Set Cursor Position in Text Area
I write this code but it does not works:
<input id="myTextInput" type="text" value="some text2">
<input type="button" value="set mouse" id="btn" />
and:
$(document).ready(function () {
$('#btn').on('click', function () {
var inp = $('#myTextInput');
var pos = 3;
inp.focus();
if (inp.setSelectionRange) {
inp.setSelectionRange(pos, pos);
} else if (inp.createTextRange) {
var range = inp.createTextRange();
range.collapse(true);
if (pos < 0) {
pos = $(this).val().length + pos;
}
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
});
});
DEMO
Where is my mistake?
Thanks
Your mistake is that you select the jQuery object instead of DOM element: replace var inp = $('#myTextInput'); with var inp = $('#myTextInput')[0];.
JSFIDDLE
However, I'd recommend using the plugin from this answer, since the code will look cleaner:
$.fn.selectRange = function(start, end) {
return this.each(function() {
if (this.setSelectionRange) {
this.focus();
this.setSelectionRange(start, end);
} else if (this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
});
};
$(document).ready(function() {
$('#btn').on('click', function() {
var pos = 7;
$('#myTextInput').focus().selectRange(pos, pos);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="myTextInput" type="text" value="some text2">
<input type="button" value="set mouse" id="btn" />
You need DOM element rather than JQuery object to use setSelectionRange or createTextRange.
Use .get(0) to retreive it.
var inp = $('#myTextInput');
inp.focus();
inp = inp.get(0);
http://jsfiddle.net/qeanb8gk/1/

Highlight Text in Text Field at a Specific Point

I'm trying to replicate Twitter's "compose new tweet" box. I have a counter that shows how many letters you have left. I'm not using HTML's maxlength, so when you go into the negatives, the counter turns red and is negative. In Twitter, your overflowed text is highlighted a light red.
How would I manage to highlight overflowed text in a text field? Here's my HTML and JavaScript that I already have. (I've attempted to highlight the text before but I didn't know where to start 'cuz I'm a noob. :P ):
<div id="char_count">
<span id="charsLeftH" title="Characters Remaining" style="cursor: pointer">500</span>
</div>
<input type="button" value="Send" id="submit">
<script>
var chars = 500;
function charsLeft() {
chars = 500 - $("#type_area").val().length;
document.getElementById("charsLeftH").innerHTML=chars;
if (chars < 50 && chars > 0) {
document.getElementById("charsLeftH").style.color="#9A9A00";
document.getElementById("submitX").id="submit";
} else if (chars < 1) {
document.getElementById("charsLeftH").style.color="#BD2031";
if (chars < 0) {document.getElementById("submit").id="submitX";}
} else {
document.getElementById("charsLeftH").style.color="#000000";
document.getElementById("submitX").id="submit";
}
};
charsLeft();
</script>
here is the script
jfiddle:
style:
<style type="text/css">
.red{
color:#F00;
}
#mytextarea{
background-color:#999;
filter:alpha(opacity=50);
opacity:0.5;
border: 1px #3399FF solid;
min-height:50px;
width:150px;
word-wrap:break-word;
}
</style>
html:
<div contenteditable="true" id="mytextarea" onChange="charsLeft(this.innerHTML)" onKeyUp="charsLeft(this.innerHTML)"></div> <div id="remaining"></div>
javascript:
<script>
var before = 1;
var chars = 10;
var len = 0;
var div = document.getElementById('mytextarea');
var el = document.getElementById('remaining');
el.innerHTML = chars;
var overchars = 92; //length of the tags
function charsLeft(val) {
if (typeof (val) != 'undefined') {
val = val.replace('<font style="background-color:#F36;" id="reddragonred">', '');
val = val.replace('</font>', "");
len = val.length;
if (len > chars) {
plusvalor = val.slice(chars, len);
redstr = '<font style="background-color:#F36;" id="reddragonred">' + plusvalor + '</font>';
blackstr = val.slice(0, chars);
div.innerHTML = blackstr + redstr;
var subj = document.getElementById('reddragonred');
var cursorepos = subj.innerHTML.length;
var range = document.createRange();
var sel = window.getSelection();
console.log(before+' '+len);
if((before>0)&&(before<len)){
console.log('no');
try{
console.log(cursorepos);
if(cursorepos==0){
range.setStart(subj, 0);
}else{
range.setStart(subj, 1);
}
}catch (e){
console.log(e);
}
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
div.focus();
}
before=len;
}
}
el.innerHTML = chars - len;
}
</script>

Categories

Resources