JS complex operation of the selected text - javascript

Great minds JavaScript, please help.
I need to deal with the complex operation of the selected text.
I have some text with a lot of html tags, and I need to get a function that returns the following result:
The user selects text in a particular tag with the class, for example <div class="text">,
and the function is activated in the event that:
$('.text').mouseup(function (e){...});
returns the beginning of the selection
returns the end of the
selection identifies a particular tag, with his class
Moreover:
the number of characters to be given html tags,
but you can exclude
some tags example ,
Ok, some code, what I have:
$(function () {
$('.text').mouseup(function (e){
$(this).highlight(getSelectionText());
})
})
this demo
Here we highlight the desired part of the text, but did not return the
correct position
In addition, the text is released coincidentally
characters, and I need it for the position

You might want to try this:
$(function () {
$('#detailBoxParagraph').mouseup(function (e){
var selectedText = getSelectionText();
$(this).removeHighlight();
$(this).highlight(selectedText);
var txt = $(this).text();
var pos = [];
var i = txt.indexOf(selectedText);
if(i > -1) {
pos.push({"start": i+1, "end": i + selectedText.length});
}
while (i != -1) {
i = txt.indexOf(selectedText, i + 1);
if(i > -1) {
pos.push({"start": i+1, "end": i + selectedText.length});
}
}
console.log(pos);
})
//alertSelection();
})

Related

Issue with the contains method and highlighting elements

I want to highlight an element that contains a string written in a textbox. This is the part of the code that's supposed to do it:
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "") {
var foundin = $('div:contains(a)');
foundin.addClass("highlighted");
alert(a);
}
})
The problem is that the whole page gets highlighted. I'm assuming this happens because I have a main container which has its children containers, so the contains method selects the whole main container. Is this the case or is it because of something else, and does anyone have a better way of doing this? Thanks in advance.
The :contains selector will return any element which contains the text you're searching for, in this case "a". This has nothing to do with the variable named a. Perhaps you meant to do something like this:
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "")
{
var foundin = $("div:contains('" + a + "')");
foundin.addClass("highlighted");
alert(a);
}
})
If I understand correctly, you only want the div highlighted which is wrapping that searchbox and not any other div. Use closest() to find that div.
$("#rightContainer .magnifier").click(function () {
var a = $("#searchBox").val();
if (a != "")
{
$("#searchBox").closest('div').addClass('highlighted');
}
})

how to highlight all the occurrence of a particular string in a div with java script?

i need to highlight all the occurrences of a string in particular div by selecting a string,
once i select a word and click a button it need to highlight all its occurrence inside a div,
eg - if i select
cricket is game
it should highlight all the occurrences of cricket is game some may be like this cricket is game or cricket is game
You can get the browser to do the hard work for you using a TextRange in IE and window.find() in other browsers.
This answer shows how to do it. It will match text that crosses element boundaries and does the highlighting for you using document.execCommand().
Alternatively, James Padolsey recently published a script that I haven't used but looks like it could help: http://james.padolsey.com/javascript/replacing-text-in-the-dom-solved/
mark.js seems pretty good for this. Here's my 3 line fiddle to take an html 'string' and highlight the search string.
$(document).ready(function() {
var html_string = "<b>Major Tom to groundcontrol.</b> Earth is blue <span> and there's something </span> i can do";
var with_highlight = $("<div/>").html(html_string).mark("can");
$("#msg").html(with_highlight);
})
Link to jsfiddle
You can tryout this script Demo
in highlightSearchTerms function of this script var bodyText = document.body.innerHTML; get replace by your divid and than it will do the task for you..
/*
* This is the function that actually highlights a text string by
* adding HTML tags before and after all occurrences of the search
* term. You can pass your own tags if you'd like, or if the
* highlightStartTag or highlightEndTag parameters are omitted or
* are empty strings then the default <font> tags will be used.
*/
function doHighlight(bodyText, searchTerm, highlightStartTag, highlightEndTag)
{
// the highlightStartTag and highlightEndTag parameters are optional
if ((!highlightStartTag) || (!highlightEndTag)) {
highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
highlightEndTag = "</font>";
}
// find all occurences of the search term in the given text,
// and add some "highlight" tags to them (we're not using a
// regular expression search, because we want to filter out
// matches that occur within HTML tags and script blocks, so
// we have to do a little extra validation)
var newText = "";
var i = -1;
var lcSearchTerm = searchTerm.toLowerCase();
var lcBodyText = bodyText.toLowerCase();
while (bodyText.length > 0) {
i = lcBodyText.indexOf(lcSearchTerm, i+1);
if (i < 0) {
newText += bodyText;
bodyText = "";
} else {
// skip anything inside an HTML tag
if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
// skip anything inside a <script> block
if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
bodyText = bodyText.substr(i + searchTerm.length);
lcBodyText = bodyText.toLowerCase();
i = -1;
}
}
}
}
return newText;
}
/*
* This is sort of a wrapper function to the doHighlight function.
* It takes the searchText that you pass, optionally splits it into
* separate words, and transforms the text on the current web page.
* Only the "searchText" parameter is required; all other parameters
* are optional and can be omitted.
*/
function highlightSearchTerms(searchText, treatAsPhrase, warnOnFailure, highlightStartTag, highlightEndTag)
{
// if the treatAsPhrase parameter is true, then we should search for
// the entire phrase that was entered; otherwise, we will split the
// search string so that each word is searched for and highlighted
// individually
if (treatAsPhrase) {
searchArray = [searchText];
} else {
searchArray = searchText.split(" ");
}
if (!document.body || typeof(document.body.innerHTML) == "undefined") {
if (warnOnFailure) {
alert("Sorry, for some reason the text of this page is unavailable. Searching will not work.");
}
return false;
}
var bodyText = document.body.innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag, highlightEndTag);
}
document.body.innerHTML = bodyText;
return true;
}
/*
* This displays a dialog box that allows a user to enter their own
* search terms to highlight on the page, and then passes the search
* text or phrase to the highlightSearchTerms function. All parameters
* are optional.
*/
function searchPrompt(defaultText, treatAsPhrase, textColor, bgColor)
{
// This function prompts the user for any words that should
// be highlighted on this web page
if (!defaultText) {
defaultText = "";
}
// we can optionally use our own highlight tag values
if ((!textColor) || (!bgColor)) {
highlightStartTag = "";
highlightEndTag = "";
} else {
highlightStartTag = "<font style='color:" + textColor + "; background-color:" + bgColor + ";'>";
highlightEndTag = "</font>";
}
if (treatAsPhrase) {
promptText = "Please enter the phrase you'd like to search for:";
} else {
promptText = "Please enter the words you'd like to search for, separated by spaces:";
}
searchText = prompt(promptText, defaultText);
if (!searchText) {
alert("No search terms were entered. Exiting function.");
return false;
}
return highlightSearchTerms(searchText, treatAsPhrase, true, highlightStartTag, highlightEndTag);
}
This should get you started: http://jsfiddle.net/wDN5M/
function getSelText() {
var txt = '';
if (window.getSelection) {
txt = window.getSelection();
} else if (document.getSelection) {
txt = document.getSelection();
} else if (document.selection) {
txt = document.selection.createRange().text;
}
document.getElementById('mydiv').innerHTML = document.getElementById('mydiv').innerHTML.split(txt).join('<span class="highlight">' + txt + '</span>');
}
See: Get selected text on the page (not in a textarea) with jQuery
If you want it to work across element boundaries your code will need to be more involved than this. jQuery will make your life easier when doing the necessary DOM traversal and manipulation.
I would use jQuery to iterate over all Elements in your div (Don't know if you have other elements in the div) and then a Regular Expression and do a greedy match to find all occurrences of the selected string in your text(s) in the elements.
First you need to find needed substrings in needed text and wrap them with <span class="search-highlight">. Every time you need to highlight another strings, you just get all the .search-highlight spans and turn their outerHtml into innerHtml.
So the code will be close to:
function highLight(substring, block) {
$(block).find(".search-highlight").each(function () {
$(this).outerHtml($(this).html());
});
// now the block is free from previous highlights
$(block).html($(block).html().replace(/substring/g, '<span class="search-highlight">' + substring + '</span>'));
}
<form id=f1 name="f1" action=""
onSubmit="if(this.t1.value!=null && this.t1.value!='')
findString(this.t1.value);return false"
>
<input type="text" id=t1 name=t1size=20>
<input type="submit" name=b1 value="Find">
</form>
<script>
var TRange=null;
function findString (str) {
if (parseInt(navigator.appVersion)<4) return;
var strFound;
if (window.find) {
// CODE FOR BROWSERS THAT SUPPORT window.find
strFound=self.find(str);
if (!strFound) {
strFound=self.find(str,0,1);
while (self.find(str,0,1)) continue;
}
}
else if (navigator.appName.indexOf("Microsoft")!=-1) {
// EXPLORER-SPECIFIC CODE
if (TRange!=null) {
TRange.collapse(false);
strFound=TRange.findText(str);
if (strFound) TRange.select();
}
if (TRange==null || strFound==0) {
TRange=self.document.body.createTextRange();
strFound=TRange.findText(str);
if (strFound) TRange.select();
}
}
else if (navigator.appName=="Opera") {
alert ("Opera browsers not supported, sorry...")
return;
}
if (!strFound) alert ("String '"+str+"' not found!")
return;
}
</script>
Much better to use rather JavaScript str.replace() function then window.find() to find all occurrences of a filter value. Iterating through the whole page might be bit complicated but if you want to search within a parent div, or within a table str.replace() is just simpler.
In your example you have only one DIV, that is even simpler. Here is what I would do (having your DIV an ID: myDIV):
//Searching for "District Court"
var filter = "District Court";
//Here we create the highlight with html tag: <mark> around filter
var span = '<mark>' + filter + '</mark>';
//take the content of the DIV you want to highlight
var searchInthisDiv = document.getElementById("MyDiv");
var textInDiv = searchInthisDiv.innerHTML;
//needed this var for replace function, do the replace (the highlighting)
var highlighted = textInDiv.replace(filter,span);
textInDiv.innerHTML = highlighted;
The trick is to replace the search string with a span that is having the filter within a tag.
str.replace replaces all occurrences of the search string, so no need to bother with looping. Loop can be used to loop through DIVs or other DOM elements.

When user enters correct text, an image rollovers/changes

I am designing a language learning site. I want to have it when someone enters text into the text box it starts to roll over certain images. Take a look at my sample below
http://imageshack.us/photo/my-images/827/hiraganaquiz2.jpg/
So, when the user enters "na" the first symbol highlights as you see in my sample. When he enters "ma" the second symbol should highlight/rollover. I want all the symbols to stay rolled over while the correct text is entered. so if the user types "nama" the first two symbols should be rolled over to show they got it correct and once the last correct text is entered all three will be rolled over.
Can this by done? I will accept advanced and simple methods.
$(document).ready(function() {
var text = ['na', 'ma', 'ba'];
$("#elemID").on('keyup', function() {
var typed = this.value;
$.each(text, function(index, item) {
if (typed.indexOf(item)!=-1) {
$('li', 'ul').eq(index).find('img').addClass('correct');
}else{
$('li', 'ul').eq(index).find('img').removeClass('correct');
}
});
});
});
FIDDLE
EDIT:
At the top of your page, in the <head> section, add:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
Then wrap the code in document.ready, see the edited code above on how to do that ?
On change of the input box, you could do something like this: (totally untested)
var parts = ["na", "ma", "blah"];
var start = 0;
for (var i = 0; i < parts.length; i++) {
var currentPart = parts[i];
var $img = $(".images img:nth-child(" + i + ")");
var end = start + currentPart.length;
if (str.length >= end && str.slice(start, start + currentPart.length) == currentPart) {
$img.addClass("highlight");
} else {
$img.removeClass("highlight");
}
start += currentPart.length;
}

Add spans to characters in a string (in an HTML element)

I want to loop through the characters of a text in an element and add spans to the characters. This is pretty easy using jQuery.map():
$elem = $('h1');
var chars = jQuery.map($elem.text().split(''), function(c) {
return '<span>' + c + '</span>';
});
$elem.html(chars.join(''));
The above works great with a simple string, but now I want to change the function so that it also will handle more 'complex' contents like: <h1>T<em>e</em><b>st</b></h1>. Which should be translated to: <h1><span>T</span><em><span>e</span></em><b><span>s</span><span>t</span></b></h1>.
This means I cannot simply loop through all the characters in the element anymore. Is there something I can use to loop through the contents (characters) of an element as well as all children? Or is there another way of achieveing what I want?
Overall idea:
You can recursively iterate over the child nodes. If you encounter an element node, you iterate over its children etc. If you encounter a text node, you are replacing it with a series of span elements.
jQuery
function wrapCharacters(element) {
$(element).contents().each(function() {
if(this.nodeType === 1) {
wrapCharacters(this);
}
else if(this.nodeType === 3) {
$(this).replaceWith($.map(this.nodeValue.split(''), function(c) {
return '<span>' + c + '</span>';
}).join(''));
}
});
}
wrapCharacters($('h1')[0]);
DEMO
JavaScript (without jQuery)
The idea stays the same, and even without jQuery, wrapping each character is not very difficult:
var d_ = document.createDocumentFragment();
for(var i = 0, len = this.nodeValue.length; i < len; i++) {
var span = document.createElement('span');
span.innerHTML = this.nodeValue.charAt(i);
d_.appendChild(span);
}
// document fragments are awesome :)
this.parentNode.replaceChild(d_, this);
Only iterating over the child nodes has to be done carefully because text nodes are getting removed during iteration.
Plain JavaScript example
Try something like (untested):
function recursivelyWrapTextNodes($node) {
$node.contents().each(function() {
var $this = $(this);
if (this.nodeType === 3) { //Node.TEXT_NODE (IE...)
var spans = $.each($this.text().split(""), function(index, element) {
var $span = $("<span></span>");
$span.text(element);
$span.insertBefore($this);
});
$this.remove();
}
else if (this.nodeType === 1) //Node.ELEMENT_NODE
recursivelyWrapTextNodes($this);
}
Example: http://jsfiddle.net/Ymcha/
This is a pure javascript solution
/**
* Enclose every character of a string into a span
* #param text Text whose characters will be spanned
* #returns {string} The "spanned" string
*/
function spanText(text) {
return "<span class='char'>" +
text.split("").join("<\/span><span class='char'>") + "<\/span>";
}
var text = "Every character will be in a span";
document.getElementById("testContent").innerHTML = spanText(text);
document.getElementById("showSpans").textContent = spanText(text);
.char{background-color: grey;}
<! --- Demo for spanning all characters -->
<h3> Spanned text is highlighted grey </h3>
<p id="testContent"> Spanned material here</p>
<h3> This is how the above Highlighted text looks </h3>
<p id="showSpans"></p>

How To Append <a></a> Tags To Specific Words In An Element With jQuery

The tricky part is not selecting the elements here, but just selecting the text within. The only true jQuery that will give you back text contents is .contents(). So I'm getting the contents of every element not he page, and I want to pick out a word, such as "hashtag". Then append to it.
What am I doing wrong here:
<html>
<p>
The word hashtag is in this sentence.
</p>
</html>
jQuery:
$(function() {
$('*')
.contents()
.filter(function(){
return this.nodeType === 3;
})
.filter(function(){
return this.nodeValue.indexOf('hashtag') != -1;
})
.each(function(){
alert("It works!")
});
});
$('*') grabs every element
.contents() grabs the contents of every element
.filter(function(){ return this.noteType === 3; refines it down to the text contents of elements. (#3 node type is text)
return this.nodeValue.indexOf('hashtag') should grab the word "hashtag". Not sure if this is working.
!= -1; should prevent it from grabbing every single element in the HTML. Not sure about that one.
Why doesn't it work? I know I have anything appending tags yet, but can I select the word "hashtag" thanks!
If you want to do this for the whole page you can work on the HTML of the body element:
$(function() {
var regExp = new RegExp("\\b(" + "hashtag" + ")\\b", "gm");
var html = $('body').html();
$('body').html(html.replace(regExp, "<a href='#'>$1</a>"));
});
Keep in mind that this may be slow if your page is large. Also, all elements will be rewritten and thus loose their event handlers etc.
If you don't want this or want to restrict the replacement to certain elements, you can select and iterate over them:
$(function() {
var regExp = new RegExp("\\b(" + "hashtag" + ")\\b", "gm");
$('div, p, span').each(function() { // use your selector of choice here
var html = $(this).html();
$(this).html(html.replace(regExp, "<a href='#'>$1</a>"));
});
});
JS :
function replaceText() {
$("*").each(function() {
if($(this).children().length==0) {
$(this).html($(this).text().replace('hashtag', '<span style="color: red;">hashtag</span>'));
}
});
}
$(document).ready(replaceText);
$("html").ajaxStop(replaceText);
HTML :
<html>
<p>
The word hashtag is in this sentence.
</p>
</html>
Fiddle : http://jsfiddle.net/zCxsY/
Source : jQuery - Find and replace text, after body was loaded
This is done with span but will work with obviously
The clean variant would be this:
$(function() {
var searchTerm = 'hashtag';
$('body *').contents()
.filter(function () {
return this.nodeType == 3
&& this.nodeValue.indexOf(searchTerm) > -1;
})
.replaceWith(function () {
var i, l, $dummy = $("<span>"),
parts = this.nodeValue.split(searchTerm);
for (i=0, l=parts.length; i<l; i++) {
$dummy.append(document.createTextNode(parts[i]));
if (i < l - 1) {
$dummy.append( $("<a>", {href: "", text: searchTerm}) );
}
}
return $dummy.contents();
})
});
It splits the value of the text node at searchTerm and re-joins the parts as a sequence of either new text nodes or <a> elements. The nodes created this way replace the respective text node.
This way all text values keep their original meaning, which cannot be guaranteed when you call replace() on them and feed them to .html() (think of text that contains HTML special characters).
See jsFiddle: http://jsfiddle.net/Tomalak/rGcxw/
I don't know jQuery very much but I think you can't just say .indexOf('hashtag'), you have to iterate through the text itself. Let's say with substring. Probably there's an jQuery function that will do this for you, but that might be your problem for finding 'hashtag'.

Categories