insert text before and after at selected text [duplicate] - javascript

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Insert text before and after the selected text in javascript
I want to put some specified text (where possible in iframe when designmode on) before and after any selected text in an HTML document. document.getSelection() or document.selection.createRange().text returns only the text itself not the position.
Is there anyway to replace the selected text?
Anyway to insert specific text before and after selcted text anywhere in the document?

I answered a related question of yours earlier today:
https://stackoverflow.com/a/8740153/96100
Also, here's an answer I posted to a remarkably similar question a year ago, recently updated to work in IE 9:
https://stackoverflow.com/a/4770592/96100
Finally, here's a version of the function from the second linked answer for your editable iframe. It allows you specify a document object:
function insertHtmlAtSelectionEnd(html, isBefore, doc) {
doc = doc || document;
var win = doc.defaultView || doc.parentWindow;
var sel, range, node;
if (win.getSelection) {
sel = win.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.collapse(isBefore);
// Range.createContextualFragment() would be useful here but was
// until recently non-standard and not supported in all browsers
// (IE9, for one)
var el = doc.createElement("div");
el.innerHTML = html;
var frag = doc.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
range = sel.createRange();
range.collapse(isBefore);
range.pasteHTML(html);
}
}

Related

How to get all elements of a selection

This is my editor content:
<h1>Heading 1<h1>
<p>Paragraph</p>
<h2>Heading 2</h2>
Now if i select text in the editor, is there a chance to get a list of all the elements involved in this selection? For example if i select a portion of Heading 1 and Paragraph i would like to get an array (h1, p) or at least an object where i can see which elements are in the selection.
Ive already tried most of the functions described here http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection but most of the time i only get the first element of the selection.
i have adapted a function i had for the same
$("textarea").select(function() {
var textComponent = $(this)[0]; //element identifier
var selectedText;
// IE version
if (document.selection !== undefined)
{
textComponent.focus();
var sel = document.selection.createRange();
selectedText = sel.text;
}
// Mozilla version
else if (textComponent.selectionStart !== undefined)
{
var startPos = textComponent.selectionStart;
var endPos = textComponent.selectionEnd;
selectedText = textComponent.value.substring(startPos, endPos);
}
$("p").html("You selected: " + selectedText);
});
check here: https://jsfiddle.net/ees8bupq/1/

JavaScript / jQuery: how to get selected text in Firefox [duplicate]

This question already has answers here:
window.getSelection() of textarea not working in firefox?
(2 answers)
Closed 3 months ago.
How can I get the selected text (in a contenteditable div) in Firefox ? It would be enough for recent versions, no need to cover old versions.
Say I have a contenteditable div that looks like the below and someone selects a text there and then hits a button, how can I copy the selected text to the clipboard or a variable ?
Example:
<div class='editInput' id='editInput'>Some awesome text</div>
My current function (working in IE):
function GetSelection()
{
if (typeof window.getSelection != "undefined")
{
var sel = window.getSelection();
if (sel.rangeCount)
{
var container = document.createElement('div');
for (var i = 0, len = sel.rangeCount; i < len; ++i)
container.appendChild(sel.getRangeAt(i).cloneContents());
return container.innerHTML;
}
}
else if (typeof document.selection != 'undefined')
if (document.selection.type == 'Text')
return document.selection.createRange().htmlText;
return '';
}
var selectedText = "" + window.getSelection();
The other suggestions didn't work for me, but the following did:
var textArea = document.getElementById('input_text_area');
var selectedText = textArea.value.substring(textArea.selectionStart,textArea.selectionEnd);
This other answer links to some background on why the above is necessary and why window.getSelection() doesn't work on Firefox, for example.

Add element before/after text selection

I'm looking for function which allows me to build some element before or after selected text. Something similar like this one javascript replace selection all browsers but for adding some content before or after selection instead of replacing it, like after() and before() jQuery methods. Should I use some DOM selection method, if yes which one? Or does exist something easier to carry it out?
Here's a pair of functions to do this.
Live example: http://jsfiddle.net/hjfVw/
Code:
var insertHtmlBeforeSelection, insertHtmlAfterSelection;
(function() {
function createInserter(isBefore) {
return function(html) {
var sel, range, node;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = window.getSelection().getRangeAt(0);
range.collapse(isBefore);
// 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);
}
} else if (document.selection && document.selection.createRange) {
// IE < 9
range = document.selection.createRange();
range.collapse(isBefore);
range.pasteHTML(html);
}
}
}
insertHtmlBeforeSelection = createInserter(true);
insertHtmlAfterSelection = createInserter(false);
})();
In MSIE:
collapse the given range and the use pasteHTML to insert the element
Others:
Also collapse the given Range and insert the element via insertNode
Both collapse-methods accept an optional argument which defines to where you want to collapse to.
If you want to put the element at the end, collapse to the end, otherwise to the start.
function yourFunction() {
const sel = window.getSelection ? window.getSelection() : document.selection.createRange()
if (!sel) return false
if (sel.getRangeAt) {
const range = sel.getRangeAt(0)
const text = range.toString()
console.log(text)
range.deleteContents()
range.insertNode(document.createTextNode(`before text${text}after`))
} else {
sel.pasteHTML(`[s=спойлер]${sel.htmlText}after`)
}
}

How to find if a HTMLElement is enclosed in Selected text

Is it possible to find out if an HTMLElement is totally enclosed within the selection?
I have a scenario where user selects some text in a HTML editor and applies some custom style from a list. Now I need to change the class attribute of each span element that is enclosed in that selection and surrounding the selection with a new span with the selected style.
Am able to find out if a particular span element is in selection by using DOM Range's compareBoundaryPoints method in firefox and safari but it will not work for IE.
Is there any way to find out if an element is totally enclosed with in the selected range for IE?
Thanks
Kapil
As #standardModel says, Rangy gives you full* DOM Range support in IE and has a helpful getNodes() method that you could use:
var sel = rangy.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
var spans = range.getNodes([1], function(node) {
return node.nodeName.toLowerCase() == "span" && range.containsNode(node);
});
// Do stuff with spans here
}
If you'd rather not use something as bulky as Rangy, the following function will tell you if an element is completely selected:
function isSelected(el) {
if (window.getSelection) {
var sel = window.getSelection();
var elRange = document.createRange();
elRange.selectNodeContents(el);
for (var i = 0, range; i < sel.rangeCount; ++i) {
range = sel.getRangeAt(i);
if (range.compareBoundaryPoints(range.START_TO_START, elRange) <= 0
&& range.compareBoundaryPoints(range.END_TO_END, elRange) >= 0) {
return true;
}
}
} else if (document.selection && document.selection.type == "Text") {
var textRange = document.selection.createRange();
var elTextRange = textRange.duplicate();
elTextRange.moveToElementText(el);
return textRange.inRange(elTextRange);
}
return false;
}
jsFiddle example: http://jsfiddle.net/54eGr/1/
(*) Apart from handling Range updates under DOM mutation
You may want to take a look at Rangy. This makes xbrowser Ranges and Selections a lot easier.

javascript replace selection all browsers

Is there a simple js function I can use to replace the current document's selection with some html of mine?
For instance say the document contains a <p>AHAHAHA</p> somewhere and user selects the 1st "ha" text chunk.
Now I want to replace this with something like: <span><font color="red">hoho</font></span>
When I google for *javascript replace selection * I can't get a simple straightforward answer!
Yes. The following will do it in all major browsers, with an option to select the inserted content afterwards as requested in the comments (although this part is not implemented for IE <= 8):
Live demo: http://jsfiddle.net/bXsWQ/147/
Code:
function replaceSelection(html, selectInserted) {
var sel, range, fragment;
if (typeof window.getSelection != "undefined") {
// IE 9 and other non-IE browsers
sel = window.getSelection();
// Test that the Selection object contains at least one Range
if (sel.getRangeAt && sel.rangeCount) {
// Get the first Range (only Firefox supports more than one)
range = window.getSelection().getRangeAt(0);
range.deleteContents();
// Create a DocumentFragment to insert and populate it with HTML
// Need to test for the existence of range.createContextualFragment
// because it's non-standard and IE 9 does not support it
if (range.createContextualFragment) {
fragment = range.createContextualFragment(html);
} else {
// In IE 9 we need to use innerHTML of a temporary element
var div = document.createElement("div"), child;
div.innerHTML = html;
fragment = document.createDocumentFragment();
while ( (child = div.firstChild) ) {
fragment.appendChild(child);
}
}
var firstInsertedNode = fragment.firstChild;
var lastInsertedNode = fragment.lastChild;
range.insertNode(fragment);
if (selectInserted) {
if (firstInsertedNode) {
range.setStartBefore(firstInsertedNode);
range.setEndAfter(lastInsertedNode);
}
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE 8 and below
range = document.selection.createRange();
range.pasteHTML(html);
}
}
Example:
replaceSelection('<span><font color="red">hoho</font></span>', true);
You can use the Rangy library
http://code.google.com/p/rangy/
You can then do
var sel = rangy.getSelection();
var range = sel.getRangeAt(0);
range.deleteContents();
var node = range.createContextualFragment('<span><font color="red">hoho</font></span>');
range.insertNode(node);

Categories