highlite text parts with jquery, best practice - javascript

i have a list of items containig names.
then i have a eventlistener, which ckecks for keypress event.
if the user types i.g. an A all names starting with an A should be viewed with the A bold. so all starting As should be bold.
what is the best way using jquery to highlite only a part of a string?
thanks for your help

Here's a function you can call during your keypress event to highlight a search string:
function Highlight(search)
{
$('ul > li').each(function() {
if (this.innerHTML.indexOf(search) > -1)
{
var text = $(this).text();
text = text.replace(search, "<span id='highlight' style='font-weight: bold'>" + search + "</span>");
$(this).html(text);
}
else
{
this.innerHTML = $(this).text();
}
});
}
Test html:
<ul id='list'>
<li>Bob Jones</li>
<li>Red Smith</li>
<li>Chris Edwards</li>
</ul>
It's not quite as elegant as Pointy's answer, but it handles the matching strings requirement.

There are jQuery plugins to do text highlighting, but I've not seen one that highlights parts of words.
One possible solution would be to put all your names on the page with the first letter surrounded by a <span> tag, with a class:
<span class='A FL'>A</span>ugustine
<span class='C FL'>C</span>arlos
You can then use jQuery to fiddle with those by class name.
$('whatever').keypress(function(ev) {
var k = e.which.toUpperCase();
$('#textContainer span.FL').css('font-weight', 'normal');
$('#textContainer span.' + k).css('font-weight', 'bold');
});
Note that bold characters are fatter than normal characters, so this is going to have a "wiggly" effect that your users might not like. You might consider changing color instead.

thanks for your help...
i figured it out and the detailed resolution comes here:
var communities = $('#mylist').find('.name');
var temp_exp = new RegExp("^("+match_string+")","i");
communities.each(function(i){
var current = $(this);
var name = current.text();
name = name.replace(temp_exp, '<b>$1</b>');
current.html(name);
});
while all items have to have the class "name".

Related

How to replace only the text of this element with jQuery?

I'm trying to make a kind of simple search engine, where
the user enters a string and if it's equal to the text inside
an element, that portion of text must be highlighted some way.
This is the html:
<input type="text">
<input type="button" value="Change text"><br>
Click here to get more info!
this is the css:
.smallcaps{
color:red;
}
and this is the jquery function that makes the search and replace:
$("input[type='button']").click(function(){
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});
This is an example of how it looks like:
Everything works fine, until the search string is equals to the name of a node element, so for example if the search string is a, the html will be broken.
How can I avoid the replace of the html itself?. I just want to work over the text.
This is the codepen:
http://codepen.io/anon/pen/mefkb
Thanks in advance!
I assume that you want to only highlight the last search and not store the ones from before.
With this assumption, you can store the old value if it is the first call and use the stored value in the calls afterwards:
$("input[type='button']").click(function(){
// Escape the html of the input to be able to search for < or >
var textValue = $('<div/>').text($("input[type=text]").val()).html();
if(textValue === '') return;
$("a").html(function(_, html) {
var old = $(this).data('content');
if(!old) {
old = html;
$(this).data('content', old);
}
var replacer = function(match) {
return match.replace(new RegExp(textValue, "ig"), '<span class="smallcaps">'+textValue+'</span>');
};
if(/[<>]/.test(old)) {
return old.replace(/^[^<>]*</gi, replacer).replace(/>[^<>]*</gi, replacer).replace(/>[^<>]*$/gi, replacer);
}
return replacer(old);
});
});
Also i fixed two bugs I found when testing:
if you search for an empty string, everything is broken.
If you search for html characters like < or > nothing is found as in the text they are converted to < or >.
One thing is not solved, as it is not possible to easily implement it without destroying the subelement structure: It is not possible to search in different subelements, as you have to remove the tags, search then and insert the tags at the right position afterwards.
Working fiddle: http://codepen.io/anon/pen/KlxEB
Updated Demo
A workaround would be to restore <a> to original text, instead of complicating the regex.
Your problem is a form the <span> tag is getting replaced.
var init = $("a").text(); //save initial value
$("input[type='button']").click(function(){
$('a').text(init); //replace with initial value
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});

Determining a character of a sentence when clicked on

On a random break I found myself wondering if it would be possible to use jQuery to determine a single character within a sentence when it is clicked on.
For example:
This
When the user clicks on first h, jQuery would return this to me.
The only way I could think of doing this would be to wrap each character within the sentence in a span with a class of its letter such as the following example:
<span class="clickable T">T</span>
<span class="clickable h">h</span>
<span class="clickable i">i</span>
<span class="clickable s">s</span>
Followed by a $('.clickable').click(function()) that would return its second class.
My question is: is this the most efficient way to do this?
Obviously wrapping every single letter of the document in span tags is not efficient.
I was able to spin something up that works in Chrome at least. Basically, when you click on a letter, it then triggers a double clicks which selects the word. We get the selection which actually gives us the text of the entire target element. From that, we get the letter that was clicked. We remove the selection and do what we want with the letter.
Fiddle here
$(function(){
$(document).click(function(e){
var target = e.target;
$(target).dblclick();
}).dblclick(function(){
var selection,
node,
text,
start,
end,
letter;
if (window.getSelection) {
selection = document.getSelection();
node = selection.anchorNode;
if (node.nodeType === 3) {
text = node.data;
start = selection.baseOffset;
end = selection.extentOffet;
if (!isNaN(start)) {
letter = text.substr(start, 1);
}
}
window.getSelection().removeAllRanges()
} else if(document.selection) {
//continue work here
}
if (letter) {
alert(letter);
}
});
});
You could return the innerHTML as well with:
$('.clickable').on('click', function(){
alert($(this).html());
});
As for a more efficient way to do it...maybe try this:
in Javascript/jQuery, how to check a specific part of a string and determine if it is a whitespace or letter?
You can do it with this script
$('.clickable').on('click', function(){
var html = $(this).text(); // if you want the text inside the span
var index = $(this).index(); // if you want the position among siblings
var classes = $(this).attr('class').split(" ");
var secondClass = getSecondClass(classes);
});
function getSecondClass(classArray){
if(classArray.length<2){
return null;
}else{
return classArray[1];
}
}
I've also included the html and index variables if you want to do something else with the clicked element.
Basically you split the classes of the element by spaces and then check if the array has less than two elements, in that case it returns null, otherwise it returns the second element.
jsFiddle
Well wrapping all text dyanamically with span tag , it is possible what you were looking for
JS
$(function(){
var lengthText = $('#singlecharacter').text().length;
var textValue = $('#singlecharacter').text();
var textArray = textValue.split('');
var newText = new Array();
for (var i = lengthText - 1; i >= 0; i--) {
newText[i] = "<span class='sp'>"+textArray[i]+"</span>";
};
$('#singlecharacter').html(newText);
$('.sp').click(function()
{
alert($(this).text());
});
});
HTML
<div id='singlecharacter'>THIS</div>
DEMO JSFIDDLE

Get initial and final position of text inside an element? - jQuery

I'm trying to learn some of jQuery/JS and I get a problem that I can't solve. I have one text like this:
blablablabla <b data-start="" data-end="">#foo</b> blablabla"
Note that I can have more than one tag in this text.
I need edit the attributes to their right values, so I was constructing a method to do this:
// "str" isn't static, but for pratical purposes, I'm using this as static.
str = 'blablablabla <b data-start="" data-end="">#foo</b> blablabla'
str.children('b').each(function(i){
$(this).attr('data-start', '');
$(this).attr('data-end', '');
})
As you can see, I don't have idea how I can do the code above. I though use:
str.children('b').each(function(i){
var start = $(this).indexOf('#');
$(this).attr('data-start', '');
$(this).attr('data-end', '');
})
But this will return the index 1, because I'm getting the index of text inside the b tag, and not inside the all text itself. So, how I can fix this problem and get initial position of "b" and final position of "b" (excluding the tag itself)?
umm.. something like this perhaps.. jsfiddle link
<span id="test" >
blablablabla <b data-start="" data-end="">#foo</b> blablabla"
</span>
and the jquery..
var str = $("#test").text();
var strB = $("#test b").text();
$("#test b").attr("data-start", str.indexOf(strB) );
$("#test b").attr("data-end", (str.indexOf(strB) + strB.length-1));
alert($("#test").html())

JQuery: nextUntil() - weird problem

I'm building a page that features a hierarchical tree-type structure. I've posted a simplified version of it at JSFiddle
It mostly works as I'd like but for one thing - on clicking closed a Brand-level row I would like, as well as the town and shoe rows to contract (which they do), for the anchors on the Town rows to change their text to '+'.
I've attempted to do so with
$(this).parent().parent().nextUntil(".TRBrand", ".TownToggle").text("+");
but try as I might it won't play nicely.
Can anyone point me in the right direction ...?
Nested lists are better for tree like structures. You can see the js is easier to write with this markup:
http://jsfiddle.net/RANmK/1/
There were several problems with your version:
The last <a> (for Reebok) had the wrong class : TRTown instead of TownToggle
Your nextUntil(...) for TownToggle was only stopping when it sees .TRTown, which means it hides too much when it is the last Town in the list and continues to hide the next brand as well. It should also stop on .TRBrasnd. You can specify both selectors by seperating them with a comma.
a.toggleTown was not targetted correctly when updating the text value to +
If I understand your requirements correctly, the following should do what you want: http://jsfiddle.net/Sx4qg/69/
$('.BrandToggle').click(function() {
var t = $(this);
var txt = t.text();
var tr = t.closest("tr");
if (txt == "+") {
tr.nextUntil(".TRBrand", ".TRTown").show();
} else {
tr.nextUntil(".TRBrand", ".TRTown, .TRShoes").hide();
tr.nextUntil(".TRBrand", ".TRTown").find("a.TownToggle").text("+");
}
t.text(txt == "+" ? "-" : "+");
});
$(".TownToggle").click(function() {
var t = $(this);
var txt = t.text();
var tr = t.closest("tr");
if (txt == "+") {
tr.nextUntil(".TRBrand,.TRTown", ".TRShoes").show();
} else {
tr.nextUntil(".TRBrand,.TRTown", ".TRShoes").hide();
}
t.text(txt == "+" ? "-" : "+");
});
Try this:
$(this).parent().parent().nextUntil(".TRBrand").find('.TownToggle').text("+");
http://jsfiddle.net/sangdol/Sx4qg/64/
Hope this fiddle will help
$(this).parent().parent().nextUntil("tr:not(.TRTown, .TRBrand)", ".TownToggle").text("+");

Does div with certain content exist

If I have a container div called #container which has a bunch of .inside divs in it, how would I go about checking whether a certain .inside div with a specified content (just a string of English text) exists or not? I'm doing this to prevent duplicates in a notification system I'm setting up for a website. I don't need the actual text - just whether it exists. Also, being able to modify the content of the .inside div if it's found would be good, so I can increment and show the number of times that message has occurred (grouping, if you like).
Thanks,
James
I like using selectors (others have used .filter, which is equally an option).
$(".inside:contains('waldo')").css({color: 'red'});
This is case sensitive.
Use the contains-selector[docs], then the length[docs] property to see how many were found.
var some_string = "test";
var els_with_string = $('#container .inside:contains(' + some_string + ')');
// use .length to check to see if there was at least one
if( els_with_string.length ) {
alert( "at least one already exists" );
}
From the docs:
Description: Select all elements that contain the specified text.
The matching text can appear directly within the selected element, in any of that element's descendants, or a combination thereof. As with attribute value selectors, text inside the parentheses of :contains() can be written as bare words or surrounded by quotation marks. The text must have matching case to be selected.
With respect to modifying the content if found, it would depend on what sort of modification you want to do. I don't know exactly what you mean by grouping.
EDIT: With respect to your comment, you could accomplish what you need like this:
var error = "ERROR:SomeError ";
var el_with_error = $('#container .inside:contains(' + error + ')');
if (el_with_error.length) {
var text = el_with_error.text();
if (/\(\d+\)/.test(text)) {
var new_text = text.replace(/\((\d+)\)/, function(s, g1) {
g1++;
return "(" + g1 + ")";
});
el_with_error.text(new_text);
} else {
el_with_error.text(text + " (2)");
}
} else {
$('#container').append('<div class="inside">' + error + '</div>');
}
Live Example: http://jsfiddle.net/ScZbV/
We could get by without the regular expression if you were able to wrap the grouping quantity in a <span> element.
var error = "ERROR:SomeError ";
var el_with_error = $('#container .inside:contains(' + error + ')');
if (el_with_error.length) {
var span = el_with_error.find('span');
if (span.length) {
var num = +span.text();
span.text( ++num );
} else {
el_with_error.append(" (<span>2</span>)");
}
} else {
$('#container').append('<div class="inside">' + error + '</div>');
}
Example: http://jsfiddle.net/ScZbV/1/
To check existence
$("#container .inside:contains('old text')").size() > 0
To modify the text
$("#container .inside:contains('old text')").text('new text');
Here's a slightly different way of looking at it...
Apply a class name for each "type" of notification. So your notification markup looks like:
<div class="inside error">Error</div>
Then inside of looking for a string inside these divs, use these new class names to your advantage and make use of .find(). If jQuery returns an object then its exists, so do something with it. But if it returns nothing then add it.
Example: http://jsbin.com/imexi4

Categories

Resources