Insert text before each line of the selected text in javascript - javascript

I have some text where I can add my text before and after selection :
Hello, I can insert text before and after this by javascript.
1. How to insert text
2. before each line
a. if text is separeted by /g
For surround selection I'm using this code:
function surroundSelection(textBefore, textAfter, color) {
if (window.getSelection) {
var sel = window.getSelection();
var selectedText = sel.toString();
if(selectedText.trim() != "") {
if (sel.rangeCount > 0) {
var range = sel.getRangeAt(0);
var startNode = range.startContainer, startOffset = range.startOffset;
var startTextNode = document.createElement(\'span\');
startTextNode.style.backgroundColor = color;
var startTextNode_t = document.createTextNode(textBefore);
startTextNode.appendChild(startTextNode_t);
var endTextNode = document.createElement(\'span\');
endTextNode.style.backgroundColor = color;
var endTextNode_t = document.createTextNode(textAfter);
endTextNode.appendChild(endTextNode_t);
var boundaryRange = range.cloneRange();
boundaryRange.collapse(false);
boundaryRange.insertNode(endTextNode);
boundaryRange.setStart(startNode, startOffset);
boundaryRange.collapse(true);
boundaryRange.insertNode(startTextNode);
range.setStartAfter(startTextNode);
range.setEndBefore(endTextNode);
sel.removeAllRanges();
sel.addRange(range);
}
}
}
}
The result after selecting text can be :
**!!its_my_text_start!!**Hello, I can insert text before and after this by javascript.
1. How to insert text
2. before each line **!!its_my_text_end!!**
a. if text is separeted by /g
But now I need to select text of the list, and put my text at the beginning and at the end of each element, which separeted by /g.
For example:
Hello, I can insert text before and after this by javascript.
**El_1_start** 1. How to insert text **El_1_end**
**El_2_start** 2. before each line **El_2_end**
**El_3_start** a. if text is separeted by /g **El_3_end**
How can I do this by using window.getSelection?

Related

How to leave the caret at its current position when replace a text in contenteditable element

I have a <span contenteditable="true">. When I move to a new line after a list or a table, I get
<div><br></div>
so to get new paragraph instead, I replace the div using
myContentEditableElement.addEventListener('keyup', function(){
if(this.innerHTML.indexOf('<div><br></div>') != -1) {
this.innerHTML = this.innerHTML.replace(/<div><br><\/div>/g,'<p><br></p>');
}
});
Now the caret moves to the start of my contenteditable element. But I need it leaves at its current position i.e. inside of the new paragraph.
I've tried
var range = document.createRange();
range.selectNodeContents(this);
var selection = window.getSelection();
range.setStart(selection.anchorNode, selection.anchorOffset);
selection.removeAllRanges();
selection.addRange(range);
but it doesn't help
I have found the answer by myself:
if(~this.innerHTML.indexOf('<div><br></div>')) {
var newLine = document.createElement('p');
newLine.innerHTML = '<br>';
var selection = window.getSelection();
var newDivNode = selection.anchorNode;
this.insertBefore(newLine, newDivNode);
this.removeChild(newDivNode);
var range = document.createRange();
range.setStart(newLine, 0);
range.setStart(newLine, 0);
selection.removeAllRanges();
selection.addRange(range);
}

How to get formatted text if selection is inside tags

If I select (highlight with mouse) bold text, I want to have <b></b> tags around it (the same goes for <i>, <span style="color:red">, <sup>, etc...).
The problem appears when You starting to select bold words inside all-bold sentence. Logically if I selected bold text - I want to copy bold text to other place. But if selection doesn't cross formatting tags I loose format info...
Here is working fiddle example: https://jsfiddle.net/xt557ov5/1/
Select just word BOLD in first line & press button.
Now select all second line, and press a button.
If you want even more magic - select just word LINE, exactly from first letter to the last (four letters no spaces around) - You also will get LINE without any bold formatting around it.
Snippet :
$('#extract').on('click', function() {
extract();
});
function extract() {
var str = getSelectionHtml();
str = str.toString().replace(/</g, "<").replace(/>/g, ">");
console.log(str);
$('#result').empty().append(str);
}
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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<button type="button" id="extract">Extract</button>
<br>
<br>
<div id="edit">
<br>
<b>Select here just word BOLD and press [Extract].</b>
<br>
<br>
<br>Now select all this <b>LINE</b>, and press [Extract].
</div>
<h4>Result:</h4>
<div id="result">
</div>
Maybe this would help: stackoverflow: Identify wether the selected text in a web page is bold or not
In order to apply it to your code I constructed this:
...
function selectionIsBold() {
var range, isBold = false;
if (window.getSelection) {
var sel = window.getSelection();
if (sel && sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
document.designMode = "on";
sel.removeAllRanges();
sel.addRange(range);
}
}
if (document.queryCommandState) {
isBold = document.queryCommandState("bold");
}
if (document.designMode == "on") {
document.designMode = "off";
}
return isBold;
}
function extract(){
var str = getSelectionHtml();
if(selectionIsBold()){
str= "<b>"+str.toString()+"</b>";
}else{
str = str.toString().replace(/</g, "<").replace(/>/g, ">");
}
$('#result').empty().append(str);
}
...
Note: selectionIsBold returns also true when thr text is "<strong>"-tagged. For other text formation checks (e.g <i>) change
isBold = document.queryCommandState("bold");
to
isBold = document.queryCommandState("italic");

Hightlight the multiple line text of div

I want to highlight the text of div tag.
It works when There is a single line but does not work for multiple:
function SelectChar(el, iStart, iLength) {
var div = el
if (document.createRange) {
var textNode = div.firstChild;
if (textNode.data.length > 1) {
var rangeObj = document.createRange();
rangeObj.setStart(textNode, iStart);
rangeObj.setEnd(textNode, iLength);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(rangeObj);
}
}
}
where textbox is content editable div tag.
UPDATE
<div contenteditable="true" id="textbox">The
text
is given
and</div>
Any suggestion please?
This is the plugin auto.js that is used to suggest the word..in that I want to do selection portion for multiple line text in div tag
AutoSuggestControl.prototype.typeAhead = function (sSuggestion /*:String*/) {
// debugger
//check for support of typeahead functionality
var range = document.createRange();
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
if (selection) {
var lastSpace = this.textbox.innerText.lastIndexOf(" ");
var lastQuote = this.textbox.innerText.lastIndexOf("'");
var lastHypen = this.textbox.innerText.lastIndexOf("-");
var lastDoubleQuote = this.textbox.innerText.lastIndexOf('"');
var lastEnter = this.textbox.innerText.lastIndexOf("\n");
var lastIndex = Math.max(lastSpace, lastEnter, lastQuote, lastHypen, lastDoubleQuote) + 1;
var contentStripped = this.textbox.innerText.substring(0, lastIndex);
var lastWord = this.textbox.innerText.substring(lastIndex, this.textbox.innerText.length);
this.textbox.innerText = contentStripped + sSuggestion; //.replace(lastWord,"");
var start = this.textbox.innerText.length - sSuggestion.replace(lastWord, "").length;
var end = this.textbox.innerText.length;
SelectChar(document.getElementById("textbox"), start, end);
}
};
jsfiddle

How to get text from selected text to end of page

I want to get all text from the selected text to end of page, that mean just the text we see on page. But when i try this, it also get text in tag 'script', 'noscript'... and other tags which not show on page:
function getTextFromCursor(){
count=0;
var allText ="";
if(window.getSelection){
var selection = window.getSelection();
var selRange = selection.getRangeAt(0);
var range = document.createRange();
range.setStart(selRange.startContainer, selRange.startOffset);
var theBody = document.getElementsByTagName('body')[0];
var lastEl = theBody.lastElementChild;
range.setEndAfter(lastEl);
allText = range.toString();
}
return allText;
}
How could i only get the text which show on page ?
The TextRange module of my Rangy library could help. It allows you to work on text as the user sees it on the page, more or less. With it, your example could be achieved with
function getTextFromCursor() {
var selection = rangy.getSelection();
var selRange = selection.getRangeAt(0);
var range = rangy.createRange();
range.selectNodeContents(document.body);
range.setStart(selRange.startContainer, selRange.startOffset);
return range.text();
}
Add the range to the selection, and use selection.toString() instead.
selection.addRange(range);
allText = selection.toString();

Set caret position right after the inserted element in a contentEditable div

I'm inserting an element into a contentEditable div but the browser sets the position of the cursor before the inserted element. Is it possible to set the cursor right after the inserted element so that the user keeps typing without having to re-adjust the cursor position?
The following function will do it. DOM Level 2 Range objects make this easy in most browsers. In IE, you need to insert a marker element after the node you're inserting, move the selection to it and then remove it.
Live example: http://jsfiddle.net/timdown/4N4ZD/
Code:
function insertNodeAtCaret(node) {
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode(node);
range = range.cloneRange();
range.selectNodeContents(node);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
var html = (node.nodeType == 1) ? node.outerHTML : node.data;
var id = "marker_" + ("" + Math.random()).slice(2);
html += '<span id="' + id + '"></span>';
var textRange = document.selection.createRange();
textRange.collapse(false);
textRange.pasteHTML(html);
var markerSpan = document.getElementById(id);
textRange.moveToElementText(markerSpan);
textRange.select();
markerSpan.parentNode.removeChild(markerSpan);
}
}
Alternatively, you could use my Rangy library. The equivalent code there would be
function insertNodeAtCaret(node) {
var sel = rangy.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode(node);
range.collapseAfter(node);
sel.setSingleRange(range);
}
}
If you're inserting an empty div, p or span, I believe there needs to be "something" inside the newly created element for the range to grab onto -- and in order to put the caret inside there.
Here's my hack that seems to work OK in Chrome. The idea is simply to put a temporary string inside the element, then remove it once the caret is in there.
// Get the selection and range
var idoc = document; // (In my case it's an iframe document)
var sel = idoc.getSelection();
var range = sel.getRangeAt(0);
// Create a node to insert
var p = idoc.createElement("p"); // Could be a div, span or whatever
// Add "something" to the node.
var temp = idoc.createTextNode("anything");
p.appendChild(temp);
// -- or --
//p.innerHTML = "anything";
// Do the magic (what rangy showed above)
range.collapse(false);
range.insertNode( p );
range = range.cloneRange();
range.selectNodeContents(p);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
// Clear the non
p.removeChild(p.firstChild);
// -- or --
//p.innerHTML = "";
Here's what worked for me, using Rangy, in a VueJS context.
// When the user clicks the button to open the popup to enter
// the URL, run this function to save the location of the user's
// selection and the selected text.
newSaveSel: function() {
if (this.savedSel) {
rangy.removeMarkers(this.savedSel);
}
// Save the location of the selected text
this.savedSel = rangy.saveSelection();
// Save the selected text
this.savedSelText = rangy.getSelection().toString();
this.showLinkPopup = true;
console.log('newSavedSel', this.savedSel);
},
surroundRange: function() {
// Restore the user's selected text. This is necessary since
// the selection is lost when the user stars entering text.
if (this.savedSel) {
rangy.restoreSelection(this.savedSel, true);
this.savedSel = null;
}
// Surround the selected text with the anchor element
var sel = rangy.getSelection();
var range = sel.rangeCount ? sel.getRangeAt(0) : null;
if (range) {
// Create the new anchor element
var el = document.createElement("a");
el.style.backgroundColor = "pink";
el.href = this.anchorHref;
el.innerHTML = this.savedSelText;
if (this.checked) {
el.target = "_blank";
}
// Delete the originally selected text
range.deleteContents();
// Insert the anchor tag
range.insertNode(el);
// Ensure that the caret appears at the end
sel.removeAllRanges();
range = range.cloneRange();
range.selectNode(el);
range.collapse(false);
sel.addRange(range);
this.showLinkPopup = false;
}
},

Categories