How to Copy the HTML Selection String with TextFormat information - javascript

I have seen answers given for Copying HTML using javascript. Almost all answers were to use clonecontents as Below
function() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
};
But here if the tags are there in the selection region, then only formatting is getting copied, else it will be copied as a Text itself. I want to copy the formatting information associated with the selection. How can i achieve this.

Test it can select with parent node
function(){
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var Node=sel.focusNode.parentNode.cloneNode(true);
//console.log(Node);
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
//
Node.innerHTML=html;
var co = document.createElement("div");
co.appendChild(Node);
html=co.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}

Related

jquery getting the html of highlighted text and changing its style

Saw this post about getting the html from the selected/higlighted text. And it does work in getting the html.
function getSelectionHtml() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
alert(getSelectionHtml());
But, suppose there's this html:
<p>I am <span style="color:green;">green</span> and I have <span style="background-color:yellow;">yellow background<span>.</p>
Now if the word green is highlighted, then it will just get the word
"green"
even if there's <span> tag surrounded. But if selected more character than the word green (say the space before or after the word green like this " green"), it will get the html tag too, such as:
<span style="color:green;">green</span>
Please check out the demo
Is it possible to get the html even if only the word "green" is highlighted?
Eventually what I want to achieve is suppose I want to change the color of the highlighted text to blue color, then first check if the highlighted text has a span. Secondly whether that span has color or background or even both styling. And lastly do the changes to the highlighted text.
$('#change_blue').on("click", function() {
var sel = getSelectionHtml();
/*var span = sel.find("<span").html();*/
alert(sel);
if (sel.match("<span style=")) {
console.log('has span tag');
if (sel.indexOf("background") > -1 && sel.indexOf("color") > -1 ) {
console.log('has both background and color')
// change color to blue
}
else if (sel.match("color")) {
console.log('only color')
// change color to blue
}
else {
console.log('only background')
// add blue color
}
}
else {
console.log('no span tag');
}
});
How can I get the html of a highlighted text and change it accordingly? It would really mean a lot if you could help me through. Thank you.
Demo
Do this,
function getSelectionHtml() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount, range; i < len; ++i) {
range = sel.getRangeAt(i);
if (range.startContainer === range.endContainer
&& range.startContainer.nodeType === Node.TEXT_NODE
&& range.startOffset === 0
&& range.endOffset === range.startContainer.length) {
range.selectNode(range.startContainer.parentElement);
}
container.appendChild(range.cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}

how to insert a link to selected text

I am trying to write a function to add links , so that my users can select a text and attach a link to the text. ( I am trying to imitate how gmail easily lets us to add,delete or edit link to a selected text inside the email)
Here is the code what I came up after Google'ng for a solution.
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
var temp = range;
var link =prompt("Please enter the link for this selection \n "+range+"","");
range.insertNode(document.createTextNode("<a href='"+link+"' target='_blank'>"+temp+"</a>"));
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
var link =prompt("Please enter the link for this selection \n "+range.text+"","");
range.text = "<a href='"+link+"' target='_blank' onClick='changeLink()'>"+range.text+"</a>";
}
The code doesn't work as I imagined, the link gets added to the content but it is showing the <a> tag also inside the content rather then showing the default blue colored text with underline. How to hide the <a> tag ? also how will I allow them to delete or edit the link.
(UPDATED) Solution :
function addFormat(type) {
var savedSel = saveSelection();
if(savedSel != '') {
var link =prompt("Please enter the link for this selection \n "+savedSel+"","");
restoreSelection(savedSel);
document.execCommand("CreateLink", false, link);
var links = getLinksInSelection();
for (var i = 0; i < links.length; ++i) {
links[i].setAttribute('target','_blank');
}
} else { alert("Please select some text to insert the link"); }
}
function getLinksInSelection() {
var selectedLinks = [];
var range, containerEl, links, linkRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
linkRange = document.createRange();
for (var r = 0; r < sel.rangeCount; ++r) {
range = sel.getRangeAt(r);
containerEl = range.commonAncestorContainer;
if (containerEl.nodeType != 1) {
containerEl = containerEl.parentNode;
}
if (containerEl.nodeName.toLowerCase() == "a") {
selectedLinks.push(containerEl);
} else {
links = containerEl.getElementsByTagName("a");
for (var i = 0; i < links.length; ++i) {
linkRange.selectNodeContents(links[i]);
if (linkRange.compareBoundaryPoints(range.END_TO_START, range) < 1 && linkRange.compareBoundaryPoints(range.START_TO_END, range) > -1) {
selectedLinks.push(links[i]);
}
}
}
}
linkRange.detach();
}
} else if (document.selection && document.selection.type != "Control") {
range = document.selection.createRange();
containerEl = range.parentElement();
if (containerEl.nodeName.toLowerCase() == "a") {
selectedLinks.push(containerEl);
} else {
links = containerEl.getElementsByTagName("a");
linkRange = document.body.createTextRange();
for (var i = 0; i < links.length; ++i) {
linkRange.moveToElementText(links[i]);
if (linkRange.compareEndPoints("StartToEnd", range) > -1 && linkRange.compareEndPoints("EndToStart", range) < 1) {
selectedLinks.push(links[i]);
}
}
}
}
return selectedLinks;
}
function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
var ranges = [];
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
ranges.push(sel.getRangeAt(i));
}
return ranges;
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}
function restoreSelection(savedSel) {
if (savedSel) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
for (var i = 0, len = savedSel.length; i < len; ++i) {
sel.addRange(savedSel[i]);
}
} else if (document.selection && savedSel.select) {
savedSel.select();
}
}
}
Thanks.

getSelection returning text after cleared

JS Fiddle
JS
function getSelectionHtml() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
console.log(html); <-- returning text even not selected.
}
$(document).ready(function(){
$(document).bind("mouseup", getSelectionHtml);
});
I'm currently trying to understand the following behavior:
1) Select a few lines of text (console.log shows those lines) - expected.
2) Click within the selection you've made. Console.log then shows the same text as the previous, which was selected. - Not expected; here I expect getSelection to return nothing as nothing is currently selected.
Can anyone tell me what i'm missing here?
Thanks!
DEMO jsFiddle
JS
var previousText = '';
function getSelectionHtml() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
if(html!= previousText) {
console.log(html);
}
previousText = html;
}
$(document).mousedown(function () {}).mouseup( function () {
getSelectionHtml();
});
To not show empty selections just change:
if(html!= previousText) {
to this:
if(html!= previousText && html != '') {
Note: I'm using jQuery because you were too

window.getSelection return html [duplicate]

This question already has answers here:
HTML of selected text
(2 answers)
Closed 9 years ago.
function selected() {
var selObj = window.getSelection();
}
This function returns selected text from a webpage. How do return the html of a selected area. Is this possible to do with an <img> and an <a> tag?
Here's the list of functions:
https://developer.mozilla.org/Special:Tags?tag=DOM&language=en
The following will do this in all major browsers and is an exact duplicate of this answer:
function getSelectionHtml() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}

HTML of selected text

Is there a cross-browser way to get HTML of selected text?
This function will do it in all major browsers:
function getSelectionHtml() {
var html = "";
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());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
// bind events for selection
document.addEventListener('mouseup', function(){
var selectedHTML = getSelectionHtml();
if( selectedHTML )
console.log( selectedHTML )
});
document.addEventListener('keyup', function(e){
var selectedHTML, key = e.keyCode || e.which;
if( key == 16 ){ // if "shift" key was released
selectedHTML = getSelectionHtml();
if( selectedHTML )
console.log( selectedHTML )
}
});
<ul contenteditable>
<li><p>Select <b>this</b> <em>text</em> right <i>here</i></p></li>
<li>Or <b>this text</b></li>
</ul>
If you just need the text of the selection, use .toString():
window.getSelection()?.toString()
'Is there a cross-browser way to get HTML of selected text?'

Categories