placeCaretAtEnd seemingly not working in Firefox - javascript

I have a content editable DIV containing a P tag with text in it and am using placeCaretAtEnd to position the caret at the end of the content inside the P tag. This seems to work well for every browser with the exception of Firefox (v32.0.3). On that, the caret just seemingly disappears.
From what I can tell, the placeCaretAtEnd JS function is supposedly fully compatible with Firefox. Any idea why this isn't working in this instance?
Working example at: http://jsfiddle.net/0ktff3zj/1/
<input id=button type=button value="Caret to end">
<div contenteditable=true>
<p id="paragraph">Sample text. Sample text.</p>
</div>
<script>
$('#button').bind('click', function() {
placeCaretAtEnd(document.getElementById('paragraph'))
});
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
</script>

I worked around this issue by placing the cursor in the contenteditable div and then using the placeCaratAtEnd function to move it.
First I gave the div an id so there would be no mix ups.
$('#button').bind('click', function() {
$('div#id').focus();
placeCaretAtEnd(document.getElementById('paragraph'))
});
I searched forever and while I know this is a bit on the hackish side, it is a solution.

Related

Is there any solution to identify <a> tag range to appear the cursor just after the end of all <a> tag

Could you please check https://jsfiddle.net/s7fxy8jp/8/
Is there any solution to identify tag range so that when I click on "Set Focus To Element Z" from the fiddle, the cursor will appear just after the end of all tag.
HTML
<div tabindex="-1" id="scripted"><a>Element A (script-only focusable)</a><a>Element B (script-only focusable)</a></div><div id="test">Set Focus To Element Z</div>
CSS
div:focus {
background-color: Aqua;}
JS
document.getElementById('test').onclick = function () {
document.getElementById('scripted').focus();};
For the cursor to appear, I believe the div must be contentEditable. You could change the attribute onClick to only make it editable after the script activates it.
Once editable you can set the selection to place the cursor position.
function cursorToEnd(el) {
var range = document.createRange();
var sel = window.getSelection();
// Note positioning after the last child works for your
// example but might not be the most robust option depending
// on your expected div contents.
range.setStartAfter(el.lastChild);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
document.getElementById('test').onclick = function () {
var e = document.getElementById('scripted');
e.contentEditable = true;
cursorToEnd(e);
};
jsFiddle
Here is this, but you won't be able to see cursor at the end because i am not converting that div into text box.
document.getElementById('test').onclick = function () {
document.getElementById('scripted').focus();
placeCaretAtEnd( document.getElementById("scripted") );
};
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
div:focus {
background-color: Aqua;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div tabindex="-1" id="scripted"><a>Element A (script-only focusable)</a><a>Element B (script-only focusable)</a></div>
<div id="test">Set Focus To Element Z</div>

Javascript range loses whitespace on Firefox?

My code is here on codepen
I am trying to count the characters and wrap those that exceed a certain limit in a <span> which I've styled as red.
The code mostly works with the exception of the function that moves the caret to the end, on Firefox the ranges I create there lose all their whitespaces so that 'abcd abcd' becomes 'abcdabcd'
Here is the code for the function:
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
// Modern browsers
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
// IE
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
Has anybody faced this before and found a solution ?
Firefox is ignoring white spaces in HTML. You have to modify it to replace space characters with html escape characters. In place of the code
inputText.substring(0,maxCharacter)
You should do
inputText.substring(0,maxCharacter).replace(/ /g, ' ')
Similarly in place of code
inputText.substring(maxCharacter)
You should do
inputText.substring(maxCharacter).replace(/ /g, ' ')
That will fix it. Hopefully it will work in all other browsers too.
Changed pen: http://codepen.io/anon/pen/GgXBjp

js/jquery: contenteditable, insert text and move cursor to end

I need to insert text into a contenteditable div and then have the cursor be at the end of the inserted text.
I got the solution below from here Insert text at cursor in a content editable div.
That works great if the text is added to am empty div. But it does not work if the user has already typed in text. Or, if the function is used to insert text, the user then places the cursor somewhere inside the newly inside text, and the function is then called again. Then the cursor is left at the beginning of the inserted text.
EDIT: The code below works in IE, properly setting the cursor, but has the problem in Chrome.
function insertTextAtCursor(text) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode( document.createTextNode(text) );
}
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().text = text;
}
}
Alright, once I realized it was a Chrome/IE thing I managed to find the answer tucked away inside one of the comments to the answer that I first found.
function insertTextAtCursor(text) {
var sel, range, html;
sel = window.getSelection();
range = sel.getRangeAt(0);
range.deleteContents();
var textNode = document.createTextNode(text);
range.insertNode(textNode);
range.setStartAfter(textNode);
sel.removeAllRanges();
sel.addRange(range);
}

How to get the text of a selection over multiple HTML elements?

Here is my question:
When the user makes a selection in an article or in the editing area of a WYSWYG editor widget,
the selection can span over multiple elements,
like anchors, images, span tags... even block-level elements (but no table in my problem).
I know how to retrieve a Range object from the selection,
but could not find a reliable solution to get the content text of the Range object.
I'm not looking for a solution for IE (its TextRange object has a .text property).
Thanks!
Have you looked at the quirksmode article on Range?
Based on this article, you could create a method like this:
function getRangeText() {
var userSelection;
if (window.getSelection) {
userSelection = window.getSelection();
} else if (document.selection) {
userSelection = document.selection.createRange();
}
var selectedText = userSelection;
if (userSelection.text) {
selectedText = userSelection.text;
}
return selectedText;
}
I tested this in FF5, Opera 11, Safari on the Mac, as well as IE6 and IE7. It's worth testing in the other IE browsers, but my guess is it works in them, as well.
This returns a string and works in all major browsers:
function getSelectionText() {
var text = ""
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type == "Text") {
text = document.selection.createRange().text;
}
return text;
}

how to modify the document selection in javascript?

I wanna modify the document selection (user currently selected by mouse or keyboard), how to do it in a cross browser way?
I have not worked with text selection enough to provide real help, but what you are trying to do can be done. You will want to look into the following two functions:
createRange() MSDN | MDC
getRangeAt() MDC
I know it can be implemented cross browser. You can see some of it in action here:
http://fuelyourcoding.com/a-few-strategies-for-using-javascript/
By scrolling to the bottom and clicking the Elephant Icon, which uses the Evernote script. However, my script first selects the main content area (you will see it flash orange) and then it deselects once the capture is made.
Here is a mini jQuery plugin that does it. It was adapted by me from some site, and like the comments say, I feel horrible for not remembering. Its really important to note I adapted it to jQuery, but the code came from some site where they explained how to do it:
// Adapted this from somewhere. Feel horrible for not remembering.
$.fn.autoSelect = function(){
var selectTarget = this[0]; // Select first element from jQuery collection
if(selectTarget != null) {
if(selectTarget.tagName == 'TEXTAREA' || (selectTarget.tagName == "INPUT" && selectTarget.type == "text")) {
selectTarget.select();
} else if(window.getSelection) { // FF, Safari, Opera
var sel = window.getSelection();
var range = document.createRange();
range.selectNode(selectTarget);
sel.removeAllRanges();
sel.addRange(range);
} else { // IE
document.selection.empty();
var range = document.body.createTextRange();
range.moveToElementText(selectTarget);
range.select();
};
};
return this; // Don't break the chain
};
It seems this script is a few places online, but here is another variation on it
As an example, and the easiest one, let's say you want to move the user's selection to contain the contents of an element. The following will work in all major browsers:
function selectElementContents(el) {
var body = document.body, range, sel;
if (body.createTextRange) {
range = body.createTextRange();
range.moveToElementText(el);
range.select();
} else if (document.createRange && window.getSelection) {
range = document.createRange();
range.selectNodeContents(el);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
}
selectElementContents( document.getElementById("someElement") );

Categories