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/
Related
i am trying to wrap the selected string between two characters
for eg: selecting 'test' and clicking on change button will change the selected text to 'atestb'
the problem is that, i am able to replace the selected text, but window.getSelection().toString() is coming empty.
This is the function that im using
replaceSelectedText(startTag, endTag) {
let sel, range;
console.log(window.getSelection().toString())
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
const selectedContent = sel.toString();
console.log("Selected Content ")
console.log(selectedContent)
let replaceDiv = startTag + selectedContent;
replaceDiv=endTag ? replaceDiv + endTag : replaceDiv;
range.insertNode(document.createTextNode(replaceDiv));
}
} else if ((document as any).selection && (document as any).selection.createRange) {
range = (document as any).selection.createRange();
range.text = startTag;
}
}
Link to Stackblitz
https://stackblitz.com/edit/angular-idyhj5?file=src%2Fapp%2Fapp.component.ts
You are deleting the value before retrieving it.
range.deleteContents();
const selectedContent = sel.toString();
If you flip those two lines and store the contents before deleting, it will work as you expect.
I'm creating a markdown editor and I need to check if neighbor characters are specific characters, then remove them, else append them.
For e.g I want to check selected-text, tow neighbor characters are **, then remove them, else append them around selected text.
I can get selected text using this approach:
function getSelection(elem) {
var selectedText;
if (document.selection != undefined) { // IE
elem.focus();
var sel = document.selection.createRange();
selectedText = sel.text;
} else if (elem.selectionStart != undefined) { // Firefox
var startPos = elem.selectionStart;
var endPos = elem.selectionEnd;
selectedText = elem.value.substring(startPos, endPos)
}
return selectedText;
}
$(document).on('mousedown', 'button', function(e) {
var selection = getSelection( $('#txtarea').get(0) );
alert(selection);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="txtarea">this is a test</textarea>
<button>Bold (toggle)</button>
Now I need when user clicks on that button, it checks if selected text is between ** like this **selectedtext**, then remove them like this selected text else append them like this **selectedtext**. How can I do that?
Before anything I would like to refer to all the markdown editors out there: https://www.google.de/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=javascript%20markdown%20library
So: do not try to reinvent the the wheel, and so on.
But for the sake of learning, my approach would look like this:
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;
});
See it in action: https://jsfiddle.net/t4ro53v8/4/
The solution takes a very generic approach: the marker to toggle is set as a custom data attribute to make it easy to reuse the code.
The functionality is only implemented for the non-IE case. You will have to check, how to determine startPos and endPos for a range in IE.
In all other browsers:
the selection is identified
nothing is done if nothing is selected
sourroundings of the selection are checked against the given marker
if both markers are present, they get deleted
otherwise the markers are inserted
As a proof of concept this example works like a charm.
But there are some shortcomings:
How to distinguish between bold text(**) and italics(*)?
How to handle markers that just appear just on one side of the selection
What to do, if a marker is selected?
But that is for you to solve now ...
You could use regex to find the occurance of a ** ** pattern.This regex will help you find the pattern similar to what you have.
[*][*][a-z]*[*][*] .
Using the exec() method, will help you extract that particular text.
Check the length of this using .length, if it is 4, then there is nothing in between, and you can replace it with the new text surrounded by **,
"**"+ newtext+"**"
For removing the **, you can use the replace() method, where you replace ** with whitespace or so.
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`)
}
}
I'm trying to read in the value of selected text within a text area. Here is my code:
function readSelected(id)
{
textarea = document.getElementById(id);
if (document.selection)
{ //Code for IE
textarea.focus();
sel = document.selection.createRange();
alert(sel.text);
}
else
{ // Code for Mozilla Firefox
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var scrollTop = textarea.scrollTop;
var scrollLeft = textarea.scrollLeft;
sel = textarea.value.substring(start, end);
alert(sel);
}
}
HTML:
<textarea id="txt1" rows="10"></textarea>
<a onclick="readSelected('txt1');">Get Selected</a>
When you click the button, a popup should occur telling you what the selected text is.
The code works in Firefox, but I can't get it to work in IE8.
The problem is that clicking on the <a> element destroys the selection. You could use an unselectable button instead:
<input type="button" value="get" onclick="readSelected('txt1');" unselectable="on">
There are other minor issues with your code
You should declare all your variables, otherwise they end up leaking into the global scope. sel and textarea are the offenders here.
scrollTop and scrollLeft are redundant.
You should test for the selectionStart and selectionEnd properties first, since they're the standard (HTML 5 specifies them and IE 9 will support them).
Here's my rewritten version:
function readSelected(id) {
var sel = "", el = document.getElementById(id);
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
sel = el.value.slice(el.selectionStart, el.selectionEnd);
} else if (document.selection && document.selection.createRange) {
el.focus();
sel = document.selection.createRange().text;
}
alert(sel);
}
Did you try with onmousedown instead of onclick ?
Here's my code:
function moremagic()
{
var txt = '';
if (window.getSelection)
{
txt = window.getSelection();
}
else if (document.getSelection)
{
txt = document.getSelection();
}
else if (document.selection)
{
txt = document.selection.createRange().text;
}
else return;
if(txt=="" || txt==" "){
alert("No Text Selected");
return;}
var start = txt.anchorOffset;
var countstring = txt.toString();
alert(txt.anchorNode);
var end = txt.anchorOffset+countstring.length;
var type = prompt("Annotation Type: ");
if(type=="lp-token"){
var description = prompt("Lisp Statement: ");}
else if(type=="section-head-annotation"){
var description = "Section Head";}
else if(type=="list-item-annotation"){
var description = "list-element";}
else if(type=="sentence-annotation"){}
else {var description = prompt("Description: ");}
Arraystring = Arraystring+"#"+type+"#"+description+"#"+start+"#"+end;
alert(Arraystring);
var custom = document.getElementById("custom");
custom.value=Arraystring;
}
It generates a textnode object from text highlighted by the cursor but this function is called many different times and for each different highlight the anchorNode changes. I need the anchorNode to be a constant for all of the created textnode objects. Is there any way that the anchorNode of a textobject can be changed? Thank you!
Not totally sure what you are trying to achieve, but in reading this http://help.dottoro.com/ljkstboe.php I would have to say "No, there is no way to make the anchorNode constant" since it is based off of the selection. Now, if you always want the reference to the first character in the selected string for a particular selection (assuming the selection is only textNode), then you might be able to do this (replacing code where your var start is):
var firstNode, start;
if(txt.anchorOffset < txt.focusOffset) {
firstNode = txt.anchorNode;
start = txt.anchorOffset;
}
else {
firstNode = txt.focusNode;
start = txt.focusOffset;
}
var countstring = txt.toString();
etc...
This is because if the selection is made from right-to-left rather than left-to-right, most browsers place the anchorNode at the last character and the focusNode at the first character of the selection, because the anchorNode indicates where the user started their selection.