How to get the highlighted texts? - javascript

I am trying to get the selected texts from the user(the highlighted text that user highlights).
I have the following:
function getSelectedTexts(){
var t = '';
if(window.getSelection){
t = window.getSelection();
console.log('1');
}else if(document.getSelection){
t = document.getSelection();
console.log('2');
}else if(document.selection){
console.log('3');
t = document.selection.createRange().text;
}
return t;
}
$('.text_speech').live('click',function(e){
e.preventDefault();
var textTest='';
textTest=getSelectedTexts();
console.log(textTest);
})
My console returns
1
>Selection <------object
anchorNode: Text
anchorOffset: 2
baseNode: Text
baseOffset: 2
extentNode: Text
extentOffset: 1
focusNode: Text
focusOffset: 1
isCollapsed: false
rangeCount: 1
type: "Range"
__proto__: Selection
I am not sure how to get the selected texts. Anyone can help me about it? Thanks a lot!

window.getSelection() returns a Selection object.
If you want to get the selected text without thinking more, you should do:
window.getSelection().toString()
But if your selection can be more complex, you should read the MDN documentation.
For example the user might select text with multiple tags:
<div class="text_speech">
<p>First paragraph</p>
<p>Second paragraph <strong>big</strong></p>
</div>
If the user select all the sentence 'paragraph Second paragraph big' then the easy way won't work.

Try:
console.log(textTest.toString());

Related

Unable to un-highlight selection in 2 different paragraphs using Rangy library

JSfiddle for reference: https://jsfiddle.net/9jp346r4/20/
I am trying to create functionality that allows user to highlight the selected text upon pressing a button, and unhighlight the highlighted text upon right-clicking.
I've gotten it mostly working using the rangy library except there's one scenario that doesn't work and I'm not sure how to solve it.
When I highlight text that is in 2 different paragraphs, it highlights it successfully.
The issue arises when I would like to come back later and un-highlight both the paragraphs.
The expected behaviour is: I right-click any highlighted text regardless of if it is selected or not and it will un-highlight all nearby highlighted text even if it's separated by a paragraph tag or strong tag.
The current behaviour is: It only unhighlights the text in the paragraph I clicked.
To re-produce:
1) Select text that overlaps both the first and second paragraph and press the "Press" button.
2) Un-select the selected text by clicking somewhere else on the screen.
3) Right-click any of the highlighted text. Notice only one of the paragraphs gets un-highlighted.
If something is unclear, feel free to ask questions. Would appreciate the help.
Here is my HTML:
<div id="content">
<p>
Paragraph 1
</p>
<p>
Paragraph 2
</p>
</div>
<div id="divId">
<input id="myBtn" type="button" value="Press" onclick = "javascript:toggleItalicYellowBg()"/>
</div>
Here is my javascript:
function coverAll() {
var ranges = [];
for(var i=0; i<window.getSelection().rangeCount; i++) {
var range = window.getSelection().getRangeAt(i);
while(range.startContainer.nodeType == 3
|| range.startContainer.childNodes.length == 1)
range.setStartBefore(range.startContainer);
while(range.endContainer.nodeType == 3
|| range.endContainer.childNodes.length == 1)
range.setEndAfter(range.endContainer);
ranges.push(range);
}
window.getSelection().removeAllRanges();
for(var i=0; i<ranges.length; i++) {
window.getSelection().addRange(ranges[i]);
}
return true;
}
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
} else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
var italicYellowBgApplier;
function toggleItalicYellowBg() {
italicYellowBgApplier.toggleSelection();
}
window.onload = function() {
$(document).on("contextmenu", ".italicYellowBg", function(e){
if(coverAll()) {
italicYellowBgApplier.undoToSelection();
return false;
}
});
rangy.init();
// Enable buttons
var classApplierModule = rangy.modules.ClassApplier;
// Next line is pure paranoia: it will only return false if the browser has no support for ranges,
// selections or TextRanges. Even IE 5 would pass this test.
if (rangy.supported && classApplierModule && classApplierModule.supported) {
italicYellowBgApplier = rangy.createClassApplier("italicYellowBg", {
tagNames: ["span", "a", "b", "img"]
});
}
};
I guess to easy solve this problem, in memory keep an array of user highlights, one item of that array is not a single highlight item, but a further "selection of selected items during the highlight", when somebody would right click on a single segment of highlight, in-memory find from array all associated highlights and unhighlight the related segments by yourself.

Get html element one after the other with JQuery

My div #chat receive some text and some select element.
I would like to get the text (in my case: 'hello how are you today') with the help of JQuery.
I tried this but it doesn't work
$('#chat').each(function(index){
if(this == 'select'){
var test=$('option:selected');
MyTable.push(test.text+" ");
}
else{
MyTable.push(this+" ");
}
});
try this
<div>
<p id="text">hello how</p>
//dropdown 1
//drop down 2
//dropdown 3
</div>
for each element use
var value = $("#yourDropDownId").text();
to get the text or use
var value = $("#yourDropDownId").val();
to get the value
then just push mytable.push(value)

Expect selected text

I can simulate text selection with protractor by a lot of different ways. But I can't find solution how I can expect that text was really selected. How I can do this without using marking?
I can simulate select text by protractor with:
DragAndDrop function (mouse)
Combination: browser.actions().sendKeys(protractor.Key.CONTROL, 'a').perform();
Combination: shift + left arrow
Elaborating Michael's comment into a working example.
In the following demo example, we are navigating to the AngularJS website, sending "testing" text to the search input on the top right, pressing left arrow 3 times to move the cursor 3 characters to the left, then pressing SHIFT + ARROW_RIGHT keyboard combination 2 times to select the next 2 characters - which is in:
Finally, we are applying the solution to get the selection text provided here and asserting:
describe("Get selection text", function () {
beforeEach(function () {
browser.get("https://angularjs.org/");
});
it("should input 'testing', select 'in' and assert it is selected", function () {
var q = element(by.name("as_q"));
// enter 'testing' and go 3 chars left
q.sendKeys("testing")
.sendKeys(protractor.Key.ARROW_LEFT)
.sendKeys(protractor.Key.ARROW_LEFT)
.sendKeys(protractor.Key.ARROW_LEFT);
// select 2 chars to the right
browser.actions()
.keyDown(protractor.Key.SHIFT)
.sendKeys(protractor.Key.ARROW_RIGHT)
.sendKeys(protractor.Key.ARROW_RIGHT)
.keyUp(protractor.Key.SHIFT)
.perform();
// get highlighted text
var highligtedText = browser.executeScript(function getSelectionText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
});
expect(highligtedText).toEqual("in");
});
});
Hope this would help you and others coming here.
Here you might also need to verify that the text inside a particular text box is selected. You can do that by using these 2 lines below:
*document.evaluate( 'XpathOfTheElement//input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.selectionStart
document.evaluate( 'XpathOfTheElement//input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.selectionEnd*
if 'in' is selected in the string 'testing' then first line will return 4 and second line will return 6.

Get all IDs of selected/highlighted DIVs

I may be going in the completely wrong direction with what I'm trying to do, so I wanted to ask for help.
Background / Overview
I need to display a paragraph of text and allow a user to select one or more words from the paragraph and save their highlighted text to a database, for just their profile. Actually, hat selection of text will eventually be (1) stored with the highlight AND (2) linked up to another set of highlighted text from another paragraph (basically, I'm tying a phrase from one source to a reference source)
What I've tried...
I have tried to put each word of the paragraph into a DIV (and a unique ID) with each DIV set to float left, so that the display looks okay.
<style>
div { float: left}
</style>
and...using an example:
<div id="GEN_1_1">
<div id="GEN_1_1_1">In</div>
<div id="GEN_1_1_2">the</div>
<div id="GEN_1_1_3">beginning</div>
<div id="GEN_1_1_4">God</div>
<div id="GEN_1_1_5">created</div>
<div id="GEN_1_1_6">the</div>
<div id="GEN_1_1_7">heaven</div>
<div id="GEN_1_1_8">and</div>
<div id="GEN_1_1_9">the</div>
<div id="GEN_1_1_10">earth</div>.
</div>
Which looks like: In the beginning God created the heaven and the earth. (minus the bold)
So far, I have used the
window.getSelection()
function to determine/grab the words that have been highlighted.
I then tried using this:
if (window.getSelection)
{
selected_len = window.getSelection().toString().length;
if (window.getSelection().toString().length>0)
{
div_id = window.getSelection().getRangeAt(0).commonAncestorContainer.parentNode.id;
}
}
to get the ID's for each DIV selected, BUT I only get a single DIV ID returned right now.
Help Request:
Is there are slick way to get the ID for each DIV selected and put it into an Array, so that I can construct a SQL query to put it into the database (the query is easy)? The selected words could total up to several hundred, if not a thousand words, so I need to make sure the solution will work with a ton of words selected.
UPDATE: JSFIDDLE DEMO
I modified the code again. See if it works for you now.
$(document).ready(function () {
$(document).on('mouseup keyup', '.checked', function () {
console.log(window.getSelection());
if (window.getSelection().toString().length>0) {
var count = window.getSelection();
var arr = [];
$('.checked span').each(function(){
var span = $(this)[0];
var isT = window.getSelection().containsNode(span, true);
if(isT){
arr.push($(this).attr('id'));
}
});
console.log(arr,count.toString());
alert(arr);
alert(count.toString());
}
});
});
I created a fiddle for solution. Check it out here: http://jsfiddle.net/lotusgodkk/GCu2D/18/
Also, I used span instead of div for the text selection. I hope that won't be an issue for you. So the code works as you want. It will return the id of the parent span in which text is selected. You can modify it to save the ID into array or as per your needs.
$(document).ready(function () {
$(document).on('mouseup', '.checked', function () {
if (window.getSelection) {
var i = getSelectionParentElement();
console.log(i);
alert('parent selected: ' + i.id);
}
});
});
function getSelectionParentElement() {
var parent = null, selection;
if (window.getSelection) {
selection = window.getSelection();
if (selection.rangeCount) {
parent = selection.getRangeAt(0).commonAncestorContainer;
if (parent.nodeType != 1) {
parent = parent.parentNode;
}
}
} else if ((selection = document.selection) && selection.type != "Control") {
parent = selection.createRange().parentElement();
}
return parent;
}

How to select the text of a span on click?

I am looking for a way to select the text inside a span using jquery when the text is clicked on.
For example in the html snippet below, I want the text "\apples\oranges\pears" to become selected when it is clicked on.
<p>Fruit <span class="unc_path">\\apples\oranges\pears</span></p>
I've tried implementing this myself to no avail.
It could be implemented with native JavaScript. A working demonstration on jsFiddle. Your code could be like this:
$('.unc_path').click(function (){
var range, selection;
if (window.getSelection && document.createRange) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(this);
selection.removeAllRanges();
selection.addRange(range);
} else if (document.selection && document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(this);
range.select();
}
});
You can use CSS to do this more easily than JS with style="user-select: all;"
add cursor: pointer; so its obvious they can click...
See code snippet:
<p>
Fruit
<span style="user-select: all; cursor: pointer;">\\apples\oranges\pears</span>
</p>
A working demonstration : http://jsfiddle.net/dystroy/V97DJ/
$('.unc_path').click(function (){
var text = $(this).text();
var $input = $('<input type=text>');
$input.prop('value', text);
$input.insertAfter($(this));
$input.focus();
$input.select();
$(this).hide();
});​
The idea (see comment above) is to dynamically replace the span with an input, only cross-browser way I know to have selected text.
Note that this is only half the road, as you probably want to deselect, style to remove border, etc.
And I must also precise that an input, contrary to a span, cannot span on multiple lines.
I don't think this could/should be used in a real application except in a very specific point.
EDIT : new version : http://jsfiddle.net/dystroy/A5ZEZ/
In this version the text comes back to normal when focus is lost.
$('.unc_path').click(function (){
var text = $(this).text();
var $this = $(this);
var $input = $('<input type=text>');
$input.prop('value', text);
$input.insertAfter($(this));
$input.focus();
$input.select();
$this.hide();
$input.focusout(function(){
$this.show();
$input.remove();
});
});​
To select the specific Span you need a id to be provided to that span. Else you need to loop through the list of all available span to get it.
Lets take this as Example (have added id attribute)
<p>Fruit <span class="unc_path" id="span1">\\apples\oranges\pears</span></p>
The JQuery will be like this
$('span1').text() // if you want to take the text
$('span1').html() // if you want to take the html

Categories