Javascript find occurance position of selected text in a div - javascript

I have a string with a word five times.if i selected forth hello it should return 4
<div id="content">hello hai hello hello hello</div>
getting selected text script
<script>
if(window.getSelection){
t = window.getSelection();
}else if(document.getSelection){
t = document.getSelection();
}else if(document.selection){
t =document.selection.createRange().text;
}
</script>
If am selecting hai it should return 1.
If am selecting hello hai it should return 1. please help.

Assuming that the contents of the <div> are guaranteed to be a single text node, this is not too hard. The following does not work in IE < 9, which does not support Selection and Range APIs. If you need support for these browsers, I can provide code for this particular case, or you could use my Rangy library.
Live demo: http://jsfiddle.net/timdown/VxTfu/
Code:
if (window.getSelection) {
var sel = window.getSelection();
var div = document.getElementById("content");
if (sel.rangeCount) {
// Get the selected range
var range = sel.getRangeAt(0);
// Check that the selection is wholly contained within the div text
if (range.commonAncestorContainer == div.firstChild) {
// Create a range that spans the content from the start of the div
// to the start of the selection
var precedingRange = document.createRange();
precedingRange.setStartBefore(div.firstChild);
precedingRange.setEnd(range.startContainer, range.startOffset);
// Get the text preceding the selection and do a crude estimate
// of the number of words by splitting on white space
var textPrecedingSelection = precedingRange.toString();
var wordIndex = textPrecedingSelection.split(/\s+/).length;
alert("Word index: " + wordIndex);
}
}
}

You'll need to use the Range capabilities of the DOM. Here is how to get the currently selected range:
var currentRange = window.getSelection().getRangeAt(0);
From there currentRage.startOffset will tell you the position of your selection within the file. So you'll need to compare that with the start range of your element:
var myContent = document.getElementById('content');
var divRange = document.createRange ();
divRange.selectNodeContents (myContent);
Now you can compare the divRange.startOffset with your selection startOffset and determine which one you're on.

Related

How to check if selected text in html already has a class?

I'm making a function that takes a selected piece of text and highlights it by adding the tag. It highlights the text but if I click the highlight button again, the text disappears. Instead, I'd just want the text to go back to being un-highlighted. Anyone have suggestions how I could go about doing this?
highLightText() {
var selection = window.getSelection();
console.log('this is the selection: ', selection);
var selection_text = selection.toString();
var mark = document.createElement('mark');
mark.textContent = selection_text;
var range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(mark);
}
My idea was to somehow check if the selected text from var selection has an element named mark in it and if it does, don't continue with the rest of the function. I'm just not exactly sure how to implement it.
You can get a reference to the node that is currently selected by using the Selection's anchorNode or focusNode and from there get the parent element of the text.
var parent = selection.anchorNode.parentElement;
From there is it just a matter of checking it's nodeName property to see if it is mark.
parent.nodeName == "MARK" //nodeName is uppercase
After that just replace the mark element with the text node and call normalize() on the grand parent element to make sure any adjacent text nodes get merged
let grandParent = parent.parentElement;
parent.replaceWith(document.createTextNode(parent.textContent));
grandParent.normalize();
This will do all the text in the mark element and not just the selected text of a mark, for that you will have to modify the code if that was the intention.
Demo (hit any key after making a selection)
function highLightText() {
var selection = window.getSelection();
var parent = selection.anchorNode.parentElement;
var selection_text = selection.toString();
if (parent.nodeName == "MARK") {
let grandParent = parent.parentElement;
parent.replaceWith(document.createTextNode(parent.textContent));
grandParent.normalize();
return;
}
var mark = document.createElement('mark');
mark.textContent = selection_text;
var range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(mark);
}
document.addEventListener('keyup',highLightText);
<div>
<div>Test one two three</div>
<div>Test four five six</div>
<div>Test seven eight nine</div>
<div>Test ten eleven twelve</div>
</div>

jQuery / Javascript insert element after the current paragraph in content editable

I am using Medium.js editor script which helps with contenteditable divs.
But I also want to make adding images better and more like Medium.js itself does.
Currently, I am using this function to insert a node at the current cursor point:
function insertImageAtCursor(text) {
var sel, range, html;
sel = window.getSelection();
range = sel.getRangeAt(0);
range.deleteContents();
var descriptionNode = document.createElement("img");
descriptionNode.className = "img";
descriptionNode.src = text;
range.insertNode(descriptionNode);
range.setStartAfter(descriptionNode);
sel.removeAllRanges();
sel.addRange(range);
}
This works, however I am facing styling issues where I am currently in a paragraph and typing, then insert an image I will end up with content like:
<p>
this is a paragraph and I have inserted a image
<img src="insertimage.png"/>
</p>
Really, I should be using the figure element and it would insert the image outside of the current paragraph. This way when I add an image, it wouldn't be added in the current p element, but instead would be added after and as a figure element. I cannot simply append the image, as I want users to be able to be editing a blog post and be able to insert an image at any point.
Any help on this? There is a plugin already:
But the dependencies required are more than I wish to use and I already have image upload etc working. Just need to get the images being inserted better.
you can split the <p> in two <p> tags and add the <img> between this <p> tags.
Here is a sample code. It's not bug free :).
http://codepen.io/anon/pen/RaOpbr
function insertImageAtCursor(text) {
var sel, range, html;
sel = window.getSelection();
range = sel.getRangeAt(0);
var para = getParagraph(range.startContainer);
range.deleteContents();
range.setEndAfter(para);
var newPara = document.createElement("p");
newPara.innerHTML = range.toString();
range.deleteContents();
para.parentElement.appendChild(newPara);
para.parentElement.insertBefore(para, newPara);
var descriptionNode = document.createElement("img");
descriptionNode.className = "img";
descriptionNode.src = text;
para.parentElement.insertBefore(descriptionNode, newPara);
range.setStart(newPara, 0);
sel.removeAllRanges();
sel.addRange(range);
}
function getParagraph(node) {
var para = node;
while (para.parentElement !== null && (para.tagName == null || para.tagName.toLowerCase() !== 'p')) {
para = para.parentElement;
}
return para;
}

Highlight text in javascript like Evernote Web Clipper

My current solution is:
Get selected html (include text and html tag), namely: selText
highlightText = <span>selText</span>
Find selText in innerHTML of the body or document (or the element which the mouse dragged in)
Replace with highlightText
But if the document is: a a a a a a and user selects the last a. My function will highlight the first or all a.
Any suggestion?
Thank you.
i think your question is duplicated, anyway i just searched the internet and found this article.
Below the final code to achieve what you ask
function highlightSelection() {
var selection;
//Get the selected stuff
if(window.getSelection)
selection = window.getSelection();
else if(typeof document.selection!="undefined")
selection = document.selection;
//Get a the selected content, in a range object
var range = selection.getRangeAt(0);
//If the range spans some text, and inside a tag, set its css class.
if(range && !selection.isCollapsed)
{
if(selection.anchorNode.parentNode == selection.focusNode.parentNode)
{
var span = document.createElement('span');
span.className = 'highlight-green';
range.surroundContents(span);
}
}
}
I also found this library rangy that is an helper you can use to select text but only works with jquery so i prefer the first vanilla-js solution.
var el = $("<span></span>");
el.text(rangy.getSelection().getRangeAt(0).toString());
rangy.getSelection().getRangeAt(0).deleteContents();
rangy.getSelection().getRangeAt(0).insertNode(el.get(0));
rangy.getSelection().getRangeAt(0).getSelection().setSingleRange(range);
On Range and User Selection
You have to select range using Document.createRange that return a Range object before you can use Range.surroundContents(), you could create a range this way.
var range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
In practice you follow this guide to understand range and selection tecniques.
The most important point is contained in this code
var userSelection;
if (window.getSelection) {
userSelection = window.getSelection();
}
else if (document.selection) { // should come last; Opera!
userSelection = document.selection.createRange();
}
After this you can use
userSelection.surroundContents()

Finding indices of highlighted text

I'm trying to save information about text that a user has highlighted in a webpage. Currently I'm using the getSelection method shown below:
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;
to retrieve the highlighted text. Then I'm searching through the entire text body and storing the indices of the highlighted text. The getSelection method only returns what text is highlighted so the problem is that if the highlighted text appears multiple times in the text body, the search could find the wrong repeat of the text and thus save the wrong indices.
Any ideas how to ensure that I'm saving the right indices?
Thanks!
QuirksMode has an article about this.
You'd probably be interested in this code:
var userSelection;
if (window.getSelection) {
userSelection = window.getSelection();
}
else if (document.selection) { // should come last; Opera!
userSelection = document.selection.createRange();
}
var rangeObject = getRangeObject(userSelection);
function getRangeObject(selectionObject) {
if (selectionObject.getRangeAt)
return selectionObject.getRangeAt(0);
else { // Safari!
var range = document.createRange();
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
return range;
}
}

How do you manipulate selected text via a Firefox extension

I'm working on a Firefox extension that will manipulate highlighted text.
On a stand-alone page, I can get the selected text with:
selectedText = document.selection?document.selection.createRange().text;
Then I'd manipulate the selected text with string operations on the textarea in question. Unfortunately, that isn't possible for a plugin since I don't know where the user's selected text is.
Is there a way get the name of the element in which text is selected or to alter selected text without the name of the element?
selectedText = content.getSelection().toString();
you need to get the range object from your user selection:
var userSelection;
if (window.getSelection)
userSelection = window.getSelection();
else if (document.selection) // should come last; Opera!
userSelection = document.selection.createRange();
var rangeObject = getRangeObject(userSelection);
...
function getRangeObject(selectionObject) {
if (selectionObject.getRangeAt)
return selectionObject.getRangeAt(0);
else { // Safari!
var range = document.createRange();
range.setStart(selectionObject.anchorNode, selectionObject.anchorOffset);
range.setEnd(selectionObject.focusNode, selectionObject.focusOffset);
return range;
}
}
...
The Range object has start and end container nodes, etc ..
more information can be found on Quirksmode here and on w3.org here

Categories

Resources