innerText polyfill for Firefox - javascript

In WebKit innerText seems to return the text of the element that the user sees which is exactly what I need.
Are there any polyfills for Firefox?
For example:
<div id='1'><br> f<div style='display:none'>no</div>oo bar</div>
<script>
function test(){ return document.getElementById('1').innerText }
</script>
The function test would return "\n foo bar".
The goal is to make an editable text area where links are clickable and where tags are highlighted and where the linking and highlighting is created on the fly while typing.
My approach is:
On every keyup:
save the cursor position
cut the text with innerText
parse the links and tags of the text returned by innerText
paste the parsed text into the editable area
restore the cursor position
Thanks!

You can use the toString() method of the Selection object in Firefox, which acts a lot like innerText. Since you're already saving the cursor position before extracting innerText in your example, the following does not bother to save and restore the selection, but otherwise you should be doing that.
function getInnerText(el) {
var text = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
sel.removeAllRanges();
var range = document.createRange();
range.selectNodeContents(el);
sel.addRange(range);
text = sel.toString();
sel.removeAllRanges();
}
return text;
}

Firefox may implement innerText since Aryeh Gregor is writing a specification for innerText.
See http://aryeh.name/spec/innertext/innertext.html and http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-February/030179.html

Related

Using JS to set cursor in a contenteditable div works fine in Chrome, but not if the div is empty

Sample of what I mean:
http://jsfiddle.net/vXnCM/3717/
<div id="editable" contenteditable="true">
text text text text <span id="test" style="color:red"></span>text text
</div>
<button id="button" onclick="setCaret()">focus</button>
<script language="javascript">
function setCaret() {
var el = document.getElementById("test");
var range = document.createRange();
var sel = window.getSelection();
range.selectNodeContents(el);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
el.focus();
}
</script>
Open the link in Chrome and click Focus, then start typing. Your new text is red.
But if you delete the "ASDF" from the HTML and run it again, your new text is black.
How can I have it be red with no starting text in the div?
(Or, equally effective, how can I have it be red and then clear the starting text from the div without losing the cursor location?)
This is a common problem. Here is some background and potential solutions (none of them are ideal):
js contenteditable - prevent from writing into newly inserted element
How to place caret inside an empty DOM Element Node
How to select a node in a range with webkit browsers?
Set cursor after span element inside contenteditable div
I'm not sure if this is what you want, but I think so, basically it's your range selection logic that needs to be revised. I don't delete the text, but highlight it so when the user types the text is removed, which I think might be what you want (a la 'start typing here').
function setCaret() {
var el = document.getElementById("test");
var range = document.createRange();
var sel = window.getSelection();
range.setStartBefore(el);
range.setEndAfter(el);
sel.addRange(range);
el.focus();
}
Checkout the forked version here:
http://jsfiddle.net/uhe76wup/
Good reference to learn about Range:
https://developer.mozilla.org/en-US/docs/Web/API/Range

Respect HTML tags inside an editable DIV

i'm trying to realize a very simple kind of wysiwyg javascript editor.
What i have:
I know, the current Javascript doesn't work by hitting the button…
wrapText = function(replacementText) {
var range, sel;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
return range.insertNode(document.createTextNode(replacementText));
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
return range.text = replacementText;
}
}
};
<a id="bold-btn">Make it Bold!</a>
<div id="editit" contenteditable="true"></div>
Now, if you mark/highlight some text inside your editable div and hit the Make it Bold - Button. The selected text will be wrapped within a <b/> tag.
The problem is that the output seems like this:
This is a sample text with a <b>bold<b/> word.
instead of:
This is a sample text with a bold word.
Any idea?
You're trying too hard ;)
What your code is doing is creating a text node, which means the contents will be text instead of being treated as html. You can just use execCommand for this instead.
For instance, "Make it Bold" just needs to call document.execCommand('bold').
You can look at Mozilla's docs for execCommand for more details.
For a really small example, take a look at the demo for wysiwyg, and then look at index.js for some ideas, or just use the library yourself.

Inserting caret after an inserted node

So I have a method that takes a tag and wraps the selected text in that tag.
function wrap(tag)
{
var sel, range;
if (window.getSelection)
{
sel = window.getSelection();
if (sel.rangeCount)
{
range = sel.getRangeAt(0);
var selectedText = range.toString();
range.deleteContents();
range.insertNode(document.createTextNode('['+tag+']'+selectedText+'[/'+tag+']'));
}
}
}
This issue with this however, is after it's done wrapping the text and inserting the node the caret (where they are typing) is placed BEFORE the inserted text.
Is there such way to insert the text and have the caret remain at the end of it?
Please note i'd prefer if this could be done without the use of jQuery or any other library. I only need it to work in webkit (Safari).
You can use the range.setStartAfter and range.setEndAfter methods to set the start and end points to the point directly after your new node. I setup a jsfiddle example here: http://jsfiddle.net/phil_mcc/tM3mA/
//move the caret
range.setStartAfter(newNode);
range.setEndAfter(newNode);
sel.removeAllRanges();
sel.addRange(range);
do this after inserting the node to the range
range.collapse(false);
this will change position of selection range to the end of the range, so my guess is it should set the cursor at end position

selection position of selected text of div using javascript

I need to get the position of the selected text within a content non-editable div (not a textarea, not a rtf editor, just a simple div)
I want to do this in order to enable users to select pieces of an article and "highlight it", by wrapping it in a span with a different background and, of course, an article is build with divs and/or p-s etc, not textareas or rtfs
Any ideas?
P.s. You can also use jQuery :D
P.s.s. I need the position of the selection, not the selection itself. Aka: it start from index I to index J. I need this because the normal method of finding the text in the parent does not always return a unique result, which would suck :)
If you just want to change the background of the selected text, the easiest way to do this is by using document.execCommand(). See my answer here: Change CSS of selected text using Javascript
//Wrap selected text in span tags with the class 'hl'
//Take some action after (in this case, a simple alert)
$("p").live("mouseup",
function() {
selection = getSelectedText();
if(selection.length >= 3) {
$(this).html($(this).html().replace(selection, $('<\/span>').attr({'class':'hl'}).html(selection).parent().html()) );
alert(selection);
}
}
);
//Grab selected text
function getSelectedText(){
if(window.getSelection){
return window.getSelection().toString();
}
else if(document.getSelection){
return document.getSelection();
}
else if(document.selection){
return document.selection.createRange().text;
}
}
Code comes from here: http://esbueno.noahstokes.com/post/92274686/highlight-selected-text-with-jquery
You can check if text is selected by running :
window.getSelection and document.getSelection() and document.selection
(because browsers can check this i different ways)
and then search for div containing this text .
 
For getting the position of the selection, try these links:
http://bytes.com/topic/javascript/answers/153164-return-selectionstart-div
Set cursor position on contentEditable <div>
Well, even though you found a solution to the problem stated in your 2nd paragraph, i don't think the answer to your main question has been given. :)
The object Selection has a property named anchorOffset, giving exactly what you asked for (the position of the selected text within an element). The above link will tell you about which browsers support it, i'm afraid IE <9 might not.
function show_selected()
{
var sel = selection();
console.log(sel.anchorOffset + ':' + sel);
}
Now if you bind show_selected to, say, mouseup, you will see the offset and the selected text printed on the js console.
The fonction selection may be the following, supposed to be cross-browser:
function selection()
{
var sel;
if(window.getSelection){
sel = window.getSelection()
}
else if(document.getSelection){
sel = document.getSelection()
}
else if(document.selection){
sel = document.selection.createRange()
}
return sel
}

Move cursor to placeholder element in a contentEditable DIV

I have a contentEditable DIV and, when the user presses a key, the underlying code is processed and replaced by updated code. Alas, this causes the cursor position to be lost.
However, in order to preserve the cursor position, I am successfully inserting a <span id="placeholder"></span> into the DIV at the correct position before processing begins. This preserves the cursor's intended position, but now I can't seem to set the range to select it.
Here's what I currently have:
function focusOnPlaceholder() {
var placeholder = document.getElementById('placeholder');
if( !placeholder ) return;
var sel, range;
if (window.getSelection && document.createRange) {
range = document.createRange();
range.selectNodeContents(placeholder);
range.collapse(true);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(placeholder);
range.select();
}
}
Any help would be appreciated, and a cross-browser solution would be incredible :)
A cross-browser solution would be to use my Rangy library and specifically the selection save/restore module, which uses a similar placeholder technique and is well tested. However, this can probably be fixed without using a library by putting some content (for example, a non-breaking space (\u00A0 or in HTML) inside your placeholder element. You may want to remove the placeholder in focusOnPlaceholder() after selecting the range.

Categories

Resources