14

How can I select the first word in a div?

I need to be able to insert a line break after the first word, or wrap it in a span tag. I need to do this for multiple divs on a page with the same class.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Evanss
  • 23,390
  • 94
  • 282
  • 505

7 Answers7

30

Replacing HTML will result in event handlers being unbound and replacing the entire text for an element will result in HTML markup being lost. The best approach leaves any HTML untouched, manipulating only the first text node of the matching element. To get that text node, you can use .contents() and .filter():

function wrapFirstWord () { 
    // Select only the first text node
    var node = $("div").contents().filter(function () { 
            return this.nodeType == 3;
        }).first(),

    // Get the text... 
        text = node.text(),

    // ... and the first word
        first = text.slice(0, text.indexOf(" "));

    if (!node.length)
        return;

    // Remove the first word from the text
    node[0].nodeValue = text.slice(first.length);

    // Add it back in with HTML around it
    node.before('<span>' + first + '</span><br/>');
};

Working demo: http://jsfiddle.net/9AXvN/

Using this method will ensure that manipulating the first word will have no unwanted side effects on the rest of the element's content.


You can easily tack this on as an extension to jQuery, with an optional value for the number of words you want to wrap:

$.fn.wrapStart = function (numWords) { 
    var node = this.contents().filter(function () { 
            return this.nodeType == 3 
        }).first(),
        text = node.text(),
        first = text.split(" ", numWords).join(" ");

    if (!node.length)
        return;

    node[0].nodeValue = text.slice(first.length);
    node.before('<span>' + first + '</span><br/>');
};

Working demo: http://jsfiddle.net/9AXvN/1/

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 2
    +1 man I was 1 minute late! Just did the same thing. http://jsfiddle.net/markcoleman/NdhSj/ – Mark Coleman Mar 28 '11 at 12:23
  • Thanks @Andy E, im not sure if im being slow, but how can I specify how many words are wrapped? – Evanss Mar 28 '11 at 16:33
  • 3
    @jdln, you can specify the number of words in the wrapStart() call. `$("div").wrapStart(2);`. Also, you should accept this answer instead of mine, as this is definitely a better way :) – Dogbert Mar 28 '11 at 16:50
  • @AndyE What does node[0].nodeValue mean? Novice trying to understand the code...does node[0] match with text and nodeValue with slice()? If so, how did you define nodeValue? – LazerSharks Dec 22 '12 at 05:20
  • @ShaltNot: `node` is the jQuery-wrapped object, so `node[0]` refers to the underlying DOM text node I selected using jQuery. It's functionally equivalent to `node.get(0)`. `nodeValue` is a property on all text nodes, it's a cross-browser compatible method of accessing the text of a text node. – Andy E Dec 22 '12 at 23:06
  • The last fiddle at least breaks if there's white space before the initial text: http://jsfiddle.net/9AXvN/911/ - perhaps a deftly placed $.trim() would do the trick. – J Griffiths Nov 01 '13 at 01:24
7

This should work:

$('div.message').each(function() {
   var html = $(this).html();
   var word = html.substr(0, html.indexOf(" "));
   var rest = html.substr(html.indexOf(" "));
   $(this).html(rest).prepend($("<span/>").html(word).addClass("em"));
});

JSFiddle

Dogbert
  • 212,659
  • 41
  • 396
  • 397
4

Now I now this has already been answered, but I am very new to jquery and thought I would give it a go. Comments please!

$('div.message').each(function(index) {
    //get the first word
    var firstWord = $(this).text().split(' ')[0];

    //wrap it with span
    var replaceWord = "<span class='myClass'>" + firstWord + "</span>";

    //create new string with span included
    var newString = $(this).html().replace(firstWord, replaceWord);

    //apply to the divs
    $(this).html(newString);
});
Andy E
  • 338,112
  • 86
  • 474
  • 445
Nick Hartley
  • 136
  • 1
  • 1
  • 6
  • The only comment I would add is that manipulating `$(this).html()` can cause unwanted side effects because it causes the contents to be removed and replaced with a fresh set of elements. This means any data or events bound to those elements will disappear. This is why I recommended altering the text node only in my answer, but it appears this is not a concern for the OP. – Andy E Mar 28 '11 at 14:10
  • Thanks. I was working on the assumption that we were dealing with just plain text divs. – Nick Hartley Mar 28 '11 at 16:26
3

basicly you can do like this

$('ELEMENT_SELECTOR').text().split(' ')[0]
Fatih Acet
  • 28,690
  • 9
  • 51
  • 58
1

Actually, if you want to use it as a plugin, so that it would do it for all the items in the selector, not only the first one, use this one:

$.fn.wrapStart = function(numWords){
    return this.each(function(){
        $this = $(this);
        var node = $this.contents().filter(function(){
            return this.nodeType == 3
        }).first(),
        text = node.text(),
        first = text.split(" ", numWords).join(" ");
        if (!node.length) return;
        node[0].nodeValue = text.slice(first.length);
        node.before('<span>' + first + '</span>');
    });
};

http://jsfiddle.net/rxAMF/

edzjins
  • 11
  • 1
1

This may help you

First Word in String with jquery

$('div.message').text(function(i,txt) {
    var name = $('div.name').text().split(' ')[ 0 ];   
});
Community
  • 1
  • 1
Vicky
  • 9,515
  • 16
  • 71
  • 88
  • This will break if there is other HTML in the `div` element. – Andy E Mar 28 '11 at 12:02
  • @jdln so you have only the div element along with text or div with other html elements? as per @Andy E comment – Vicky Mar 28 '11 at 12:06
  • I have control over the html output so I can put a div around the text. Thanks – Evanss Mar 28 '11 at 13:34
  • This didnt work for me but maybe im using it wrong. Is 'message' the container div and 'name' the new div thats created? – Evanss Mar 28 '11 at 14:04
0
/*
URL → https://github.com/melbon/jquery.useWord
*/
$.fn.lastWord = function() {
  var text = this.text().trim().split(" ");
  var last = text.pop();
  this.html(text.join(" ") + (text.length > 0 ? " <span class='lastWord'>" + last + "</span>" : last));
};


$.fn.firstWord = function() {
  var text = this.text().trim().split(" ");
  var first = text.shift();
  this.html((text.length > 0 ? "<span class='firstWord'>"+ first + "</span> " : first) + text.join(" "));
};


$("#firstWord").firstWord();
$("#lastWord").lastWord();
TheMadCat
  • 107
  • 1
  • 7