set cursor between 2 letters in contenteditable - javascript

How do I set the cursor between the a and the b below?
<div contenteditable = true id = "test">
abcdefg
</div>
I have tried to play with ranges, but nothing is working for me. The below code selects the entire text, and there is no cursor. (This code is for Chrome)
sel = window.getSelection();
range = document.createRange();
node = document.getElementById("test");
range.setStart(node, 0);
range.setEnd(node, 1);
sel.addRange(range);

This should work:
function setSelectionRange(aNode, aOffset) {
aNode.focus();
var sel = window.getSelection(),
range = sel.getRangeAt(0);
range.collapse(true);
range.setStart(aNode.childNodes[0], aOffset),
sel.removeAllRanges();
sel.addRange(range);
}
setSelectionRange(document.getElementById("test"), 1);
http://jsfiddle.net/5a9uD/1/
If you look to MDN documentation https://developer.mozilla.org/en-US/docs/Web/API/range.setStart you will see that this interface use a node not an element.

Related

Autocomplete Suggestion on <p> Tag Without Dropdown

I'm trying to make autocomplete (without dropdown) to a contenteditable paragraph tag. How to select remaining suggested letters in contenteditable p tag with javascript/jQuery while user typing?
// On typing
$(document).on('input', '.cell-input', function(e) {
var userInput = e.target.innerText;
// Suggested 'Bond' to user, because user typed (assumption) 'B'
e.target.innerText = 'Bond';
// Select
$(e.target).selectText(1, 3);
});
// To select
jQuery.fn.selectText = function(startPos, endPos){
var doc = document;
var element = this[0];
if (doc.body.createTextRange) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
}
else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
};
Select all is working fine. Then I tried adding:
selection.moveEnd("character", endPos);
selection.moveStart("character", startPos);
or
range.moveEnd("character", endPos);
range.moveStart("character", startPos);
.. but no luck. Am I in the right direction? Please advice.
Using setStart() and setEnd()
$(document).on('input', '.cell-input', function(e) {
var userInput = e.target.innerText;
// Suggested 'Bond' to user, because user typed (assumption) 'B'
e.target.innerText = 'Bond';
// Select
$(e.target).selectText(1, 4);
});
// To select
jQuery.fn.selectText = function(startPos, endPos) {
var doc = document;
var element = this[0];
if (doc.body.createTextRange) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
range.setStart(element.firstChild, startPos);
range.setEnd(element.firstChild, endPos);
selection.removeAllRanges();
selection.addRange(range);
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="cell-input" contenteditable="true">B</p>
Note: Using element.firstChild may not work with HTML child nodes

Insert span-node and continue writing

I have a problem adding nodes to a editable div.
I want to add highlighted text in a span and after that the cursor should be outside the added span.
Right now the cursor is inside the added span.
I have created a Fiddle to demonstrate it:
http://jsfiddle.net/4N4ZD/633/
Here is some code:
function insertNodeAtCaret() {
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
range.collapse(false);
var span = document.createElement('span');
span.innerHTML = 'TEXT';
span.style.background = 'yellow';
range.insertNode(span);
range = range.cloneRange();
range.selectNodeContents(span);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
Found a solution. Here is a fiddle: http://jsfiddle.net/4N4ZD/638/
The trick is to add a new text-span and use the methode 'setStartAfter' like so:
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
var span = document.createElement('span');
span.innerHTML = 'TEXT';
span.style.background = 'yellow';
range.insertNode(span);
var textNode = document.createTextNode('\u00A0');
range.setStartAfter(span);
range.insertNode(textNode);
range.setStartAfter(textNode);
range.collapse(true);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}

How to insert new <div> on a button click at the cursor position of existing <div>

this.$el.find('#divname').append(newDivHtml) will append to the newDivHTML to existing div. However, I was looking at this scenario:
On the existing div1 user edits some free text and clicks a button
on click of the button, a popupview shows up a list of options.
selecting one option inserts the newDivHtml into the cursor position of underlaying div1.
I tried: http://jsfiddle.net/jwvha/1/
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
2. doesn't seems to work for that.$e1.find('#sectionContentSimple').insertAdjacentHTML(100, newhtml);
Just a thought without delving into the code too deeply, have you tried saving the clicked element to a variable so that you can access it later, rather than relying on it retaining focus?

How to select DOM node in javascript in IE8?

Does anyone know how to select node (element) in IE8 in javascript?
Not using third-party libs is preferred.
In IE9 you can do like this:
var sel = window.getSelection();
sel.removeAllRanges();
var range = document.createRange();
range.selectNode(node);
sel.addRange(range);
How you can do this in IE8?
For older IE it's this, provided node is an element:
var range = document.body.createTextRange();
range.moveToElementText(node);
range.select();
For a full cross-browser solution, see
https://stackoverflow.com/a/2044793/96100
Here is the code I use, it should work across the board:
var sel, range;
if(window.getSelection && document.createRange) {
range = document.createRange();
range.selectNodeContents(node);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if(document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(node);
range.select();
}

Positioning cursor after inserted word

I want to position a cursor after an inserted word (test), in textarea.
The insertion of the word can be in any position in textarea.
(Internet Explorer)
This is my script:
document.activeElement.focus();
document.selection.createRange().text = "test";
var sel = document.selection.createRange();
sel.moveStart('character', -document.activeElement.value.length);
var cursorPos = sel.text.length;
var range = this.textarea.createTextRange();
range.collapse(true);
range.moveEnd('character', cursorPos);
range.moveStart('character', cursorPos);
range.select();
This will do it (in Internet Explorer only, you'll need a totally different approach for other browsers):
document.activeElement.focus();
var sel = document.selection.createRange();
sel.text = "test";
sel.collapse(false);
sel.select();

Categories

Resources