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?'
Related
While type the text in 4th row very fast ("Apple") the auto selection not works properly as expected. But while editing the single text it works as expected(selection works). Please check the below html sample
https://jsplayground.syncfusion.com/3ruatvy0
HTML5 Editable Table
Apple
Orange
Mango
</table>
<script>
var data = [];
$("table tr").each(function(i, v){
$(this).children('td').each(function(ii, vv){
data.push($(this).text());
});
})
console.log(data);
document.getElementById("table").addEventListener("keyup", event => {
for (var i = data.length -1 ; i > 0; i--) {
var cell = data[i - 1];
if (
event.key == "Backspace" ||
event.key == "Delete" ||
event.key == "Escape"
) {
return;
} else if (cell) {
var elem = document.getElementById("editable");
var textLen = elem.innerHTML.length;
if (
elem.innerHTML.toUpperCase() ==
cell.toUpperCase().slice(0, textLen)
) {
elem.innerText = cell;
var startNode = document.getElementById(
"editable"
).firstChild;
startNode.nodeValue = startNode.nodeValue.trim();
var range = document.createRange();
range.setStart(startNode, textLen);
range.setEnd(startNode, startNode.textContent.length);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
return;
}
} else return;
}
});
</script>
I have a form in which some elements are loaded by ajax according to user selection. I try to insert some symbols into the textarea in the form by javascript. I use last focused method with inserttext function. Function only insert symbols into the textarea but not dynamically loaded textarea.Javascript code is at the end of body.
Thanks in advance.
AJAX:
function fetch_no_answer_choice(val){
$.ajax({
type: 'POST',
url: 'fetch_no_answer_choice.php',
data: {'get_option' : val},
success: function (response) {document.getElementById("choice").innerHTML=response;}
});
}
fetch_no_answer_choice.php
<?php
if(isset($_POST['get_option'])){
$choice = $_POST['get_option'];
if ($choice !== 0){
$ans = array('A','B','C','D','E','F','G','H','I','J');
$no = 0;
for ($no = 0; $no<$choice; $no++){
echo'<textarea name = "textarea_'.$ans[$no].'" ></textarea> }
}
exit();
}
?>
JAVASCRIPT
var lastFocused;
$("textarea").focus(function() {
lastFocused = document.activeElement;
});
function insertText(text) {
var input = lastFocused;
console.log(input);
if (input == undefined) { return; }
var scrollPos = input.scrollTop;
var pos = 0;
var browser = ((input.selectionStart || input.selectionStart == "0") ?
"ff" : (document.selection ? "ie" : false ) );
if (browser == "ie") {
input.focus();
var range = document.selection.createRange();
range.moveStart ("character", -input.value.length);
pos = range.text.length;
}
else if (browser == "ff") { pos = input.selectionStart };
var front = (input.value).substring(0, pos);
var back = (input.value).substring(pos, input.value.length);
input.value = front+text+back;
pos = pos + text.length;
if (browser == "ie") {
input.focus();
var range = document.selection.createRange();
range.moveStart ("character", -input.value.length);
range.moveStart ("character", pos);
range.moveEnd ("character", 0);
range.select();
}
else if (browser == "ff") {
input.selectionStart = pos;
input.selectionEnd = pos;
input.focus();
}
input.scrollTop = scrollPos;
}
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;
}
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
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;
}