I have a span, it becomes editable after double clicking on it. However, some text is selected due to double click and I remove that selection using this code:
function removeSelectedText(element) {
if (window.getSelection || document.getSelection) {
oSelection = (window.getSelection ? window:document).getSelection();
oSelection.removeAllRanges();
} else {
document.selection.empty();
}
}
After this operation, now-editable non-selected span loses focus. All I want to move the caret to the last clicked place in the span. I try the code below but didn't work ('element' is span itself):
...
var selection = (window.getSelection ? window:document).getSelection();
var position = selection.getRangeAt(0).focusOffset;
element.focus();
var range = document.createRange();
range.setStart(element, position);
range.setEnd(element, position);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
I try whatever I found but couldn't get it working. I can't focus it anymore due to frustration. That would be awesome if you help me...
UPDATE: In range.setStart() and range.setEnd(), element.firstChild should be used instead of element.
A similar problem and its solution is here, I am surprised for finding it in the second day of search considering my offensive search yesterday. Any better solution is welcomed, since even this one cannot bypass text selection at first double click.
Related
I can not come up with a suitable solution...
<p class="session" contenteditable="true">
Everything contained <b>**within**</b> this div is editable in browsers
that support <code>`HTML5`</code>. Go on, give it a try: click it and
start typing.
</p>
I want to add the appropriate HTML-tags while typing.
Of course it is no problem doing it by simple regex replacements. But I have problems setting the caret at the right place.
Say, in the example above, I want to emphasize the word "try". While typing the right * first and then the left star *, the text is converted to <i>*try*</i> but I want to preserve the position of the caret (set the the caret after the left *). And of cource vice versa, where the right * is set at last.
I find it more difficult to set the part contained <b>**within**</b> this say underlined. _contained <b>**within**</b> this_ becomes <u>_contained <b>**within**</b> this_</u>. So we are not in the same node.
I can think of complicated solutions, but since I am no expert in these text conversions techniques (range, window selection etc.) I wonder if there is a well known pratice of doing it.
Check out the Fiddle
I have tried to get the caret position as a first step and in the second step i have tried to put the caret back to the position .
$('.session').keyup(function(){
//alert("happening");
var sel = window.getSelection();
var offset=sel.anchorOffset;
// you can change the text in div by uncommeting the line below and replace your text with mathcing regex .
//$('.session').text($('.session').text().replace('/(\*.\*)+/','<i>$1<i>'));
setCaret(offset);
$('.session')
});
function setCaret(offset) {
var el = $('.session');
//alert();
var range = document.createRange();
var sel = window.getSelection();
range.setStart(el[0].childNodes[0],offset);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
el.focus();
}
You need to figure out how to change the text in the div as per your needs. While replacing the text inside the div also maintain the formatting so that the solution works.
I'm using Froala 2 and the documentation doesn't seem to have anything that implies a simple way to set the location of the caret, let alone at the beginning or end. I'm trying to seed the editor instance with a little content in certain cases and when I do using html.set, the caret just stays where it is at the beginning and I want to move it to the end. The internet doesn't seem to have anything helpful around this for v2.
Froala support provided an answer for me that works:
var editor = $('#edit').data('froala.editor');
editor.selection.setAtEnd(editor.$el.get(0));
editor.selection.restore();
As far as I know, Froala 2 doesn't provide any API to do this, but you can use native JavaScript Selection API.
This code should do the job:
// Selects the contenteditable element. You may have to change the selector.
var element = document.querySelector("#froala-editor .fr-element");
// Selects the last and the deepest child of the element.
while (element.lastChild) {
element = element.lastChild;
}
// Gets length of the element's content.
var textLength = element.textContent.length;
var range = document.createRange();
var selection = window.getSelection();
// Sets selection position to the end of the element.
range.setStart(element, textLength);
range.setEnd(element, textLength);
// Removes other selection ranges.
selection.removeAllRanges();
// Adds the range to the selection.
selection.addRange(range);
See also:
How to set caret(cursor) position in contenteditable element (div)?
Set caret position at a specific position in contenteditable div
This feels like a stupid question.
I'm using the excellent Rangy library in javascript to apply CSS classes from a dropdown to selected text, as if in a rich text editor.
But if the user is simply typing text without making a selection, and they apply a class via a dropdown, rangy's "applyToSelection" does nothing since,presumably, it's an empty range.
I know there are difficult ways to add a proper div at the selected cursor location and enter into it, but, before I embark on those, am I missing a simple way to do it, either using Rangy or normal JS?
Thanks!
Here's the code I ended up with, which worked perfectly in IE11 but has not been tested in other browsers yet:
var actual_textarea = document.getElementById("my_input_textarea");
actual_textarea.focus();
var selectedInstance = this.ne.selectedInstance;
var range = selection.getRangeAt(0);
range.deleteContents();
var new_div = document.createElement("div");
new_div.innerHTML = "<div class='" + this.rangyClassPrefix + elm + "'></div>";
var frag = document.createDocumentFragment();
var node, lastNode;
while (node = new_div.firstChild)
{
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
if (lastNode)
{
range = range.cloneRange();
range.selectNodeContents(lastNode);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
Notice that I set focus first since the style is being applied by focus-changing clicks on other elements.
I'm still a little fuzzy at the thought of range clones being value rather than reference clones but still working perfectly when added, since that's counterintuitive, but it does work.
Thanks!
I have a contenteditable div, in which I have a span tag, which contains some text. How do I select the span tag and all of its contents, so when the user presses backspace or delete, the span and its contents get removed?
UPDATE: When I say select, I mean highlight. Sorry for the inconvenience.
UPDATE 2: I'm thinking along the lines of 'element.outerHTML.select()'. See if that helps.
In Firefox you have the Selection API which allows you to do that. Combine it with the DOM2 Range API and you have what you want:
var r = document.createRange();
r.selectNode(domElement);
var s = window.getSelection();
s.removeAllRanges();
s.addRange(r);
The Selection API found its way in a future standard, HTML Editing APIs, but it will be a while until it becomes available in a majority of browsers.
yesterday I answered your other question. I revised the jsfiddle accompanying that answer, please recheck it. Use shift+delete from within an editable span to bring up a dialog and to 'select' the current span.
Try this:
var span = document.getElementById("myspan");
span.onclick = function() {
var range = document.createRange();
range.selectNodeContents(span);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
};
I have an editable div and I am using a button to insert an image into the div. Right now, I am just doing document.getElementById('elementid').innerHTML. += ; in order to get the image added to the end of the div. I would like to enter the image where the caret is. How would I go about doing this?
Thanks
To insert an element at the caret is not too hard. The following function inserts a node at the caret (or at the end of the selection, if content is selected) in all major browsers:
function insertNodeAfterSelection(node) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode(node);
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.collapse(false);
html = (node.nodeType == 3) ? node.data : node.outerHTML;
range.pasteHTML(html);
}
}
I hate to sound negative, but this is so hard it's ridiculous. You have to deal with IE and others, and the implementations are vastly different. But where it gets uber-hard is that if you click a button to insert the image, you lose focus and the caret position, so you need to remember the position with some onblur bookmarking ability (again, IE different). The focus thing is not so much an issue if your editablecontent is in an iframe and maintains its own focus. (Note: not dissing IE here, I actually prefer their implementation to the W3C standard drek.)
You can look at some open source text editors for clues and hints. But you'll find an enormous amount of code to handle these simple tasks.
Does this help: http://jsfiddle.net/8akDr/