How can I keep text highlighting after pasting? - javascript

I have a small markdown editor
Demo
HTML:
<textarea id="txtarea">this is a **test**</textarea>
<button data-marker="**">Bold (toggle)</button>
<button data-marker="~~">Strike through (toggle)</button>
<button data-marker="*">Italics (toggle)</button>
JS:
function toggleMarker(marker, el) {
var markerLength = marker.length;
var startPos, endPos, selection, range;
if (document.selection != undefined) { // IE
el.focus();
range = document.selection.createRange();
selection = range.text;
} else if (el.selectionStart != undefined) { // Firefox
startPos = el.selectionStart;
endPos = el.selectionEnd;
selection = el.value.substring(startPos, endPos);
}
if (!selection.length){
return;
}
if (el.value.substring(startPos-markerLength,startPos) === marker
&& el.value.substring(endPos,endPos+markerLength) === marker
){
el.value = el.value.substring(0,startPos-markerLength) +
selection +
el.value.substring(endPos+markerLength);
}
else{
el.value = el.value.substring(0,startPos) + marker +
selection + marker + el.value.substring(endPos);
}
}
$(document).on('mousedown', 'button', function(e) {
toggleMarker( $(this).data('marker'), $('#txtarea').get(0) ).text;
});
Now I need to keep the highlighting of pasted text. How can I do that?

http://codepen.io/medinasod/pen/GoOrwq
JS:
var markerLength,
startPos,
endPos,
selection,
range;
function selectText(startPos, endPos, markerLength, marker) {
mytxtarea = document.getElementById("txtarea");
window.setTimeout(function() {
if (mytxtarea.value.substring(startPos-markerLength,startPos) === marker && mytxtarea.value.substring(endPos,endPos+markerLength) === marker) {
mytxtarea.setSelectionRange(startPos+markerLength, endPos+markerLength);
} else {
mytxtarea.setSelectionRange(startPos+markerLength, endPos+markerLength);
}
}, 0);
}
function toggleMarker(marker, el) {
markerLength = marker.length;
if (document.selection != undefined) { // IE
el.focus();
range = document.selection.createRange();
selection = range.text;
} else if (el.selectionStart != undefined) { // Firefox
startPos = el.selectionStart;
endPos = el.selectionEnd;
selection = el.value.substring(startPos, endPos);
}
if (!selection.length){
return;
}
if (el.value.substring(startPos-markerLength,startPos) === marker
&& el.value.substring(endPos,endPos+markerLength) === marker
){
el.value = el.value.substring(0,startPos-markerLength) +
selection +
el.value.substring(endPos+markerLength);
}
else{
el.value = el.value.substring(0,startPos) + marker +
selection + marker + el.value.substring(endPos);
}
selectText(startPos, endPos, markerLength, marker);
}
$(document).on('mousedown', 'button', function(e) {
toggleMarker( $(this).data('marker'), document.getElementById('txtarea'));
});
HTML:
<textarea id="txtarea">this is a test</textarea>
<button data-marker="**">Bold (toggle)</button>
<button data-marker="~~">Strike through (toggle)</button>
<button data-marker="*">Italics (toggle)</button>

Related

Input custom US telephone mask omitted while backspacing

I've created a custom US telephone mask on input using jQuery like -
(___) ___-____
It's working fine on keydown event.
var telMask = "(___) ___-____";
var phoneNumberBuffer = "";
$(document).ready(function () {
$(".telephone").focus(function () { handleFocus(this); });
$(".telephone").blur(function () { handleBlur(this); });
$(".telephone").keydown(function (event) { formatPhoneNumber(this, event); });
});
function mergePhoneMask() {
var tempMask = telMask;
var tempPos;
for (var i = 0; i < phoneNumberBuffer.length; i++) {
tempPos = tempMask.indexOf("_");
tempMask = tempMask.substr(0, tempPos) + phoneNumberBuffer.charAt(i) + tempMask.substr(tempPos + 1);
}
return tempMask;
}
function setPhoneNumCursor(elem) {
var position = $(elem).val().indexOf("_");
if (position < 0) { position = $(elem).val().length; }
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(position, position);
}
else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', position);
range.moveStart('character', position);
range.select();
}
}
function formatPhoneNumber(elem, e) {
var tempMask = telMask;
var tempPos;
if (e.which == 8) {
phoneNumberBuffer = phoneNumberBuffer.substr(0, phoneNumberBuffer.length - 1);
elem.value = mergePhoneMask();
}
if ((e.which > 47 && e.which < 58) || (e.which > 95 && e.which < 106)) {
if (phoneNumberBuffer.length < 10) {
// numpad keys don't match to charcode
if (e.which > 95 && e.which < 106) {
phoneNumberBuffer += (e.which - 96).toString();
} else {
phoneNumberBuffer += String.fromCharCode(e.which);
}
elem.value = mergePhoneMask();
}
}
//e.preventDefault();
if (phoneNumberBuffer.length == 10 || e.which == 9) {
//$(elem).parent().next().next().find("input").focus();
} else {
setPhoneNumCursor(elem);
}
}
function handleFocus(elem) {
if (elem.value == "") {
elem.value = telMask;
}
setPhoneNumCursor(elem);
}
function handleBlur(elem) {
if (elem.value == telMask) {
elem.value = "";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="control-input">
<input name="telephone" maxlength="14" class="telephone" type="tel" size="14" autocomplete="tel">
</div>
Problem is, while continuing to press the backspace/delete, it removes the "(" at the beginning. I'm not sure if I missed anything here! I've some limitations to use other plugins. Thanks!
I've created a JSFiddle here!

Why does Javascript not focus dynamically loaded element

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;
}

i cant hide jquery autocomplete with my functions

I am creating project which it searches musics dynamicly with JSON.
Here is my html:
<div id="custom-search-input">
<div class="input-group col-md-12">
<input type="text" class="form-control input-lg" placeholder="Search query..." id="searchquery" autocomplete="off" />
<span class="input-group-btn">
<button class="btn btn-info btn-lg" type="button" id="searchbuttonheader" onclick="search();">
<i class="glyphicon glyphicon-search"></i>
</button>
</span>
</div>
</div>
My search function called search(); ... Before I integrated jquery autocomplete I made when I click ENTER on keyboard in searchquery input it executes search(); function. To do this here is my JS code:
// ENTER KEY SEARCH //
$.fn.enterKey = function (fnc) {return this.each(function () {$(this).keypress(function (ev) {
var keycode = (ev.keyCode ? ev.keyCode : ev.which);
if (keycode == '13') {search();}})})
}
$("#searchquery").enterKey(function () {search();});
// ENTER KEY SEARCH //
OKAY ITS WORKING... BUT...
After integration the jquery autocomplete when I type something in searchquery input it gives some autocomplete data. Here is JS:
$('#searchquery').autoComplete({
minChars: 1,
delay: 500,
source: function(term, response){
$.getJSON('<?php echo $url_autocomplete; ?>', { query: term }, function(data){ response(data); });
},
onSelect: function(e, term, item){
search();
//alert('Item selected by '+(e.type == 'keydown' ? 'pressing enter' : 'mouse click')+'.');
}
});
When I click one of them the autocomplete hides and searches the text. But when I don't select any of them and hit enter it searches but the autocomplete is not hiding.
I WANT:
When I type something in searchquery input then I hit enter hide autocomplete suggestions and make search();.
You are not using jquery-ui-autocomplete but you use jQuery-autoComplete from Pixabay am I right? Ok, after see the code, there's no close method provided, so i add one to the original source code. You can copy and use below's jquery.auto-complete.js and call $("#searchquery").autoComplete('close'); to close the suggestion. See below example how to use it :
$("#searchquery").enterKey(function (e) {
$("#searchquery").autoComplete('close');
// .. DO YOUR SEARCH HERE ..
});
Use below's modified jquery.auto-complete.js.
/*
jQuery autoComplete v1.0.7
Copyright (c) 2014 Simon Steinberger / Pixabay
GitHub: https://github.com/Pixabay/jQuery-autoComplete
License: http://www.opensource.org/licenses/mit-license.php
*/
(function($){
$.fn.autoComplete = function(options){
var o = $.extend({}, $.fn.autoComplete.defaults, options);
// public methods
if (typeof options == 'string') {
this.each(function(){
var that = $(this);
if (options == 'destroy') {
$(window).off('resize.autocomplete', that.updateSC);
that.off('blur.autocomplete focus.autocomplete keydown.autocomplete keyup.autocomplete');
if (that.data('autocomplete'))
that.attr('autocomplete', that.data('autocomplete'));
else
that.removeAttr('autocomplete');
$(that.data('sc')).remove();
that.removeData('sc').removeData('autocomplete');
} else if (options == 'close') {
// Add new method to close the suggestion box
$(that.data('sc')).hide();
}
});
return this;
}
return this.each(function(){
var that = $(this);
// sc = 'suggestions container'
that.sc = $('<div class="autocomplete-suggestions '+o.menuClass+'"></div>');
that.data('sc', that.sc).data('autocomplete', that.attr('autocomplete'));
that.attr('autocomplete', 'off');
that.cache = {};
that.last_val = '';
that.updateSC = function(resize, next){
that.sc.css({
top: that.offset().top + that.outerHeight(),
left: that.offset().left,
width: that.outerWidth()
});
if (!resize) {
that.sc.show();
if (!that.sc.maxHeight) that.sc.maxHeight = parseInt(that.sc.css('max-height'));
if (!that.sc.suggestionHeight) that.sc.suggestionHeight = $('.autocomplete-suggestion', that.sc).first().outerHeight();
if (that.sc.suggestionHeight)
if (!next) that.sc.scrollTop(0);
else {
var scrTop = that.sc.scrollTop(), selTop = next.offset().top - that.sc.offset().top;
if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0)
that.sc.scrollTop(selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight);
else if (selTop < 0)
that.sc.scrollTop(selTop + scrTop);
}
}
}
$(window).on('resize.autocomplete', that.updateSC);
that.sc.appendTo('body');
that.sc.on('mouseleave', '.autocomplete-suggestion', function (){
$('.autocomplete-suggestion.selected').removeClass('selected');
});
that.sc.on('mouseenter', '.autocomplete-suggestion', function (){
$('.autocomplete-suggestion.selected').removeClass('selected');
$(this).addClass('selected');
});
that.sc.on('mousedown', '.autocomplete-suggestion', function (e){
var item = $(this), v = item.data('val');
if (v || item.hasClass('autocomplete-suggestion')) { // else outside click
that.val(v);
o.onSelect(e, v, item);
that.sc.hide();
}
return false;
});
that.on('blur.autocomplete', function(){
try { over_sb = $('.autocomplete-suggestions:hover').length; } catch(e){ over_sb = 0; } // IE7 fix :hover
if (!over_sb) {
that.last_val = that.val();
that.sc.hide();
setTimeout(function(){ that.sc.hide(); }, 350); // hide suggestions on fast input
} else if (!that.is(':focus')) setTimeout(function(){ that.focus(); }, 20);
});
if (!o.minChars) that.on('focus.autocomplete', function(){ that.last_val = '\n'; that.trigger('keyup.autocomplete'); });
function suggest(data){
var val = that.val();
that.cache[val] = data;
if (data.length && val.length >= o.minChars) {
var s = '';
for (var i=0;i<data.length;i++) s += o.renderItem(data[i], val);
that.sc.html(s);
that.updateSC(0);
}
else
that.sc.hide();
}
that.on('keydown.autocomplete', function(e){
// down (40), up (38)
if ((e.which == 40 || e.which == 38) && that.sc.html()) {
var next, sel = $('.autocomplete-suggestion.selected', that.sc);
if (!sel.length) {
next = (e.which == 40) ? $('.autocomplete-suggestion', that.sc).first() : $('.autocomplete-suggestion', that.sc).last();
that.val(next.addClass('selected').data('val'));
} else {
next = (e.which == 40) ? sel.next('.autocomplete-suggestion') : sel.prev('.autocomplete-suggestion');
if (next.length) { sel.removeClass('selected'); that.val(next.addClass('selected').data('val')); }
else { sel.removeClass('selected'); that.val(that.last_val); next = 0; }
}
that.updateSC(0, next);
return false;
}
// esc
else if (e.which == 27) that.val(that.last_val).sc.hide();
// enter or tab
else if (e.which == 13 || e.which == 9) {
var sel = $('.autocomplete-suggestion.selected', that.sc);
if (sel.length && that.sc.is(':visible')) { o.onSelect(e, sel.data('val'), sel); setTimeout(function(){ that.sc.hide(); }, 20); }
}
});
that.on('keyup.autocomplete', function(e){
if (!~$.inArray(e.which, [13, 27, 35, 36, 37, 38, 39, 40])) {
var val = that.val();
if (val.length >= o.minChars) {
if (val != that.last_val) {
that.last_val = val;
clearTimeout(that.timer);
if (o.cache) {
if (val in that.cache) { suggest(that.cache[val]); return; }
// no requests if previous suggestions were empty
for (var i=1; i<val.length-o.minChars; i++) {
var part = val.slice(0, val.length-i);
if (part in that.cache && !that.cache[part].length) { suggest([]); return; }
}
}
that.timer = setTimeout(function(){ o.source(val, suggest) }, o.delay);
}
} else {
that.last_val = val;
that.sc.hide();
}
}
});
});
}
$.fn.autoComplete.defaults = {
source: 0,
minChars: 3,
delay: 150,
cache: 1,
menuClass: '',
renderItem: function (item, search){
// escape special characters
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
},
onSelect: function(e, term, item){}
};
}(jQuery));

Replace text and following letter with other text

I am making a syntax highlighter in jQuery, and I would like to be able to show escap-tion (e.g. \n). Currently, my code just replaces \ with <span style="color:#3b73e3;">\\</span> (the first \ is for... well... escap-tion). What I would like is if it could replace \ and the following letter with <span style="color:#3b73e3;">\\(the escaped letter)</span>.
The current .replace code:
String.prototype.replaceAllTxt = function() {
return this.toString().replace(/\$slc/g, '*select')
.replace(/\$/g, "!dol")
.replace(/:/g, "$cln")
.replace(/\//g, "$slh")
.replace(/\./g, "$per")
.replace(/#/g, "$at")
.replace(/%/g, "$prc")
.replace(/"/g, "*")
.replace('*select', '<span id="select"></span>')
.replace(/\*([^\*]+)\*/g, '<span style="color:#16630D">"$1"</span>')
.replace(/\$cln/g, '<span style="color:#ff755d">:</span>')
.replace(/\$at/g, '<span style="color:#ff26b6">#</span>')
.replace(/\$prc/g, '<span style="color:#9e26ff">%</span>')
.replace(/\$per/g, '<span style="color:#00bbff">.</span>')
.replace(/\$slh/g, '<span style="color:#3b73e3;">/</span>')
.replace(/\\/g, '<span style="color:#3b73e3;">\\</span>')
.replace(/!dol/g, '<span style="color:#9b1940;font-weight:bold;">$</span>')
.replace(/\$cln/g, ":")
.replace(/\$slh/g, "/")
.replace(/\$per/g, ".")
.replace(/\$at/g, "#")
.replace(/\$prc/g, "%")
.replace(/\*/g, '"')
.replace(/!dol/g, '$');
};
Everything so far:
String.prototype.replaceAllTxt = function() {
return this.toString().replace(/\$slc/g, '*select')
.replace(/\$/g, "!dol")
.replace(/:/g, "$cln")
.replace(/\//g, "$slh")
.replace(/\./g, "$per")
.replace(/#/g, "$at")
.replace(/%/g, "$prc")
.replace(/"/g, "*")
.replace('*select', '<span id="select"></span>')
.replace(/\*([^\*]+)\*/g, '<span style="color:#16630D">"$1"</span>')
.replace(/\$cln/g, '<span style="color:#ff755d">:</span>')
.replace(/\$at/g, '<span style="color:#ff26b6">#</span>')
.replace(/\$prc/g, '<span style="color:#9e26ff">%</span>')
.replace(/\$per/g, '<span style="color:#00bbff">.</span>')
.replace(/\$slh/g, '<span style="color:#3b73e3;">/</span>')
.replace(/\\/g, '<span style="color:#3b73e3;">\\</span>')
.replace(/!dol/g, '<span style="color:#9b1940;font-weight:bold;">$</span>')
.replace(/\$cln/g, ":")
.replace(/\$slh/g, "/")
.replace(/\$per/g, ".")
.replace(/\$at/g, "#")
.replace(/\$prc/g, "%")
.replace(/\*/g, '"')
.replace(/!dol/g, '$');
};
function replaceText(oldText, newText, node){
node = node || document.body; // base node
var childs = node.childNodes, i = 0;
while(node = childs[i]){
if (node.nodeType == 3){ // text node found, do the replacement
if (node.textContent) {
node.textContent = node.textContent.replace(oldText, newText);
} else { // support to IE
node.nodeValue = node.nodeValue.replace(oldText, newText);
}
} else { // not a text mode, look forward
replaceText(oldText, newText, node);
}
i++;
}
}
function codeBox(el) {
pasteHtmlAtCaret('$slc');
$(el).css('color', '#153A7D').each(function () {
setTimeout(function() {
var txt = $(el).text();
var newtxt = txt.replaceAllTxt();
$(el).html(newtxt);
});
});
setTimeout(function() {
$('#select').focus().select().remove();
}, 1);
}
$.fn.codeBox = function () {
$(this).css('color', '#153A7D').each(function () {
var txt = $(this).text();
var newtxt = txt.replaceAllTxt();
$(this).html(newtxt);
});
};
function wait(run, ms) {
setTimeout(run(),ms);
}
function loop (run, ms) {
setInterval(run(), ms);
}
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();
}
}
function pasteHtmlAtCaret(html, selectPastedContent) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// only relatively recently standardized and is not supported in
// some 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);
}
var firstNode = frag.firstChild;
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
if (selectPastedContent) {
range.setStartBefore(firstNode);
} else {
range.collapse(true);
}
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if ( (sel = document.selection) && sel.type != "Control") {
// IE < 9
var originalRange = sel.createRange();
originalRange.collapse(true);
sel.createRange().pasteHTML(html);
if (selectPastedContent) {
range = sel.createRange();
range.setEndPoint("StartToStart", originalRange);
range.select();
}
}
}
function selectElementText(el, win) {
win = win || window;
var doc = win.document, sel, range;
if (win.getSelection && doc.createRange) {
sel = win.getSelection();
range = doc.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
} else if (doc.body.createTextRange) {
range = doc.body.createTextRange();
range.moveToElementText(el);
range.select();
}
}
$(document).ready(function() {
$('p').each(function () {
$(this).html($(this).html().replace(/\n/g, "<br>"));
});
//$('code').each(function() {
// $(this).before('<span class="code" style="font-family:Source Code Pro, monospace;background-color:#e8e8e8;">'+$(this).text()+'</span>').remove();
// c
// console.log ('code')
//});
$('code').codeBox();
$("#edit").keypress(function() {
setTimeout(function() {
codeBox("#edit");
}, 1);
});
$('#highlight').click(function() {
$("#code").codeBox();
})
});
.code {
font-family:'Source Code Pro', monospace;
}
<script src="http://code.jquery.com/jquery-2.1.4.js"></script>
<pre data-syntax="default" id="code">$(document).ready(function() {
alert ("The highlighting is ready. Email me at admin#example for more details.\nThis page has a 100% chance of loading.";
}
I would like for \n to look like </pre><span style="color:#3b73e3;">\n</span>, the same for \anything.
<div class="button" id="highlight">Highlight!</div>
JsFiddle: http://jsfiddle.net/zoweb/zuc5f7w8/
NOTE: Some of the functions in the snippet above are taken from other SO answers, and many are not being used.
You want to capture the next symbol, and this is done by using parentheses:
console.log("stuff\\ntext".replace(/\\(\w)/g, '<span style="color:#3b73e3;">\\$1</span>'));
This will only work for escaped sequences ("\\n"), because plain '\n' is one character.

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