20

In javascript/jQuery, is there a way to identify a word in a text block/paragraph? For example, say I have the following paragraph:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris suscipit interdum fermentum. Aenean fermentum imperdiet augue, et venenatis lectus semper vel. Phasellus faucibus nulla in quam egestas eleifend. Cras tristique augue eget libero tristique condimentum. Mauris eget diam eget risus feugiat rutrum. Duis placerat lorem quis augue semper porttitor. Nullam iaculis dui feugiat erat condimentum rutrum. Sed at accumsan diam. Maecenas ut urna id velit posuere auctor in vel dui. Aenean consectetur dui in leo faucibus sed feugiat dui blandit. In accumsan diam vitae erat volutpat volutpat aliquam nunc euismod. Vivamus viverra lorem nulla. Quisque justo quam, adipiscing sit amet auctor non, laoreet sit amet nisl. Donec euismod lorem ac mi dictum volutpat. Donec ligula mi, varius ac auctor at, sollicitudin id elit. In auctor sodales ipsum nec consectetur. Sed lacinia varius nibh vitae vulputate.

If I hover my mouse cursor over the first word, "Lorem", I would like it to become bold (for example). Basically, I would like just the text that the cursor is over to have a CSS property added to it on mouseover, then have that CSS property removed when the cursor is no longer on top of that word.

The only way I can think of doing this is to add a <span> tag between each and every word. Is this the only way? Is there a more efficient way perhaps, or does jQuery's mouseover event only work within tags? Can it work in identifying text blocks?

5
  • 3
    Is this the only way? Yes pretty much. Is there a more efficient way perhaps... No not really... you can't really pluck a word out of a text node and style it then and there. ...or does jQuery's mouseover event only work within tags? Can it work in identifying text blocks? No. It can work over any element; not parts of an element. Commented Jul 28, 2011 at 21:13
  • 1
    You might want to look into the Lettering.js plugin, as it was designed to make what you're doing somewhat easier.
    – Pointy
    Commented Jul 28, 2011 at 21:19
  • You'll be able to use caretPositionFromPoint() once that spec becomes more than a draft (presuming the method stays in) and browsers start implementing it... In, say, 4 years.
    – mercator
    Commented Jul 28, 2011 at 21:42
  • Some duplicates of this question may be found here: google.com/… Commented Feb 20, 2013 at 18:26
  • Also, this question discusses ways to find an individual word under the cursor: stackoverflow.com/questions/2444430/… Commented Feb 20, 2013 at 19:19

6 Answers 6

20

This seems like a good task for http://letteringjs.com/

You can set it up to create the spans for you at word barriers.

JSFiddle with your example: http://jsfiddle.net/3HdKH/

From their tutorial: https://github.com/davatron5000/Lettering.js/wiki/Wrapping-words-with-lettering%28%27words%27%29

Using:

$(document).ready(function() {
  $(".word_split").lettering('words');
});

This

<p class="word_split">Don't break my heart.</p>

Becomes:

<p class="word_split">
  <span class="word1">Don't</span>
  <span class="word2">break</span>
  <span class="word3">my</span>
  <span class="word4">heart.</span>
</p>

Then you can use the following CSS:

.word_split span:hover {
    font-weight:bold;
}
4
  • 3
    The best way really.. but heed the developers warning (to the OP) "Be smart and use sparingly. You'll probably break your browser if you try to wrap every letter on your page in a span tag" Commented Jul 28, 2011 at 21:43
  • Would it be possible to highlight individual letters on mouseover (instead of individual words)? Commented Feb 20, 2013 at 19:45
  • @Davy, I have text that's output to the screen based on javascript logic... It's updated with dialog_text as such: $('#npc_dialog_dictionary_chinese').html(dialog_text);... I tried using his function $("#npc_dialog_dictionary_chinese").lettering('words'); but it doesn't work for the outputted text... do you know why?
    – user3871
    Commented Aug 29, 2013 at 19:29
  • I am trying to apply same effect on each character and text have some links. But i couldn't find any solution. Commented Dec 11, 2021 at 14:22
5

Here's a technique I've used that wraps span tags around all words in a parent element so that they can be highlighted on hover:

const parentElement = document.getElementById('parent');

parentElement.onmouseover = e => {
  e.target.innerHTML = e.target.innerText.replace(/([\w]+)/g, '<span>$1</span>');
};
p#parent span:hover {
  background: yellow;
  cursor: pointer;
}
<p id="parent">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me?" he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. </p>

This code adds a click handler for words in list items:

parentElement.onmouseover = e => {
  if (e.target.nodeName === 'LI') {
    e.target.innerHTML = 
      e.target.innerText.replace(/([\w]+)/g, '<span>$1</span>');
    e.target.onclick = e => {
      doSomething(e.target.textContent);
    };
  }
}
1
  • Hi, what if I want to use every single letter in the text, what will the regex look like
    – Abel Agoi
    Commented Aug 5, 2020 at 8:56
1
$("p:contains(Lorem)").each(function(){
  $(this).html($(this).text().replace(/(Lorem)/, '<span class="highlightWord">$1</span> '));
});

This taken from here

2
  • How would you know which word was highlighed? Commented Jul 28, 2011 at 21:19
  • @Tom Squires there we go... had to fix something. You would know because you have applied a class to it. That class will be defined in your css with font-weight: bold; Commented Jul 28, 2011 at 21:22
1
$('span').each(function(){
    $(this).html(
            $(this)
                .text()
                .split(' ')
                .map(function(x){return "<word>"+x+"</word>";})
                .join(' ')
       )
});
$('word').hover(function(){
        $(this).css(/*highlight*/);            
},function(){
        $(this).css(/*de-highlight*/);   
});
0

The only way you can do this is with spans (as you described). Javascript sees the block of text as one element unless its broken up. You can only do things on elements. Since all the text flows and dosent have a position you cant pinpoint the individual word position to see when its hovered. Unless your text is huge a few extra span breaks shouldn't be a big issue for performance.

0

That is the only way I can think of. You might be able to do something using mouse events and mouse location (attempt to figure out what word is at the location), but it wouldn't be the funnest thing to try. You'd probably need to add some tags around words for reference points.

If you're going to break it up into elements I'd suggest using a single character tag, like <p>.

Another in-between option would be to just the over event on the container, and only break the text into sub-elements if the user hovers. Something like:

$('#container').live('mouseenter',function(){
var jThis = $(this);
var text = jThis.text();
jThis.attr('original',text);
text = text.split(' ');
var out_text = '';
for(var nI = 0; nI < text.length; nI++){
out_text += "<p>"+text[nI]+"</p>";
}
jThis.html(out_text);
});
$('#container p').live('mouseenter',function(){
$(this).addClass('highlight');
});

You'd need to add the out events too.

Not the answer you're looking for? Browse other questions tagged or ask your own question.