0

I want to capitalise the first letter of a string. That part is done.

I can capitalise div.title elements and other elements with no child nodes no proble.

What i want to do it call the text node and change only the first text node.

Therefore I would like to convert all fcn objects to uppercase.

I have the following html:

<div class="title">Me & you 
 <div class="subtitle">Me & you</div>
</div> 
<br /> 
<div class="title">Me & you</div>

and the following Jquery:

function capitalise(str) {
if (!str) return;
var stopWords = ['a', 'an', 'and', 'at', 'but', 'by', 'far', 'from', 'if', 'into', 'of', 'off', 'on', 'or', 'so', 'the', 'to', 'up'];
str = str.replace(/\b\w+\b/ig, function(match) {
    console.log(match)
    return $.inArray(match, stopWords) == -1 ? match.substr(0, 1).toUpperCase() + match.substr(1) : match;
});
return str;
}

//Capitalise subtitles
$('div.subtitle').each(function() {
    $(this).text(capitalise($(this).text()));

});

//Capitalise Titles with no children
$('div.title').filter(function() {
    return !$(this).children().length;
}).each(function() {
    $(this).text(capitalise($(this).text()));
});

var fcn = $('div.title').contents().filter(function() { return this.nodeType === 3;});

alert(fcn);
console.log(fcn);

I want to capitalise the fcn variable array. Tried various methods without success.

http://jsfiddle.net/bizwizone/wMCEa/1/

Any thoughts?

Paul
  • 175
  • 1
  • 13

2 Answers2

3

Have you considered using CSS?

.title, .subtitle {
    text-transform: capitalize;
}

If you want to capitalize the text in .title, but not child nodes, you could do this:

.title {
    text-transform: capitalize;
}
.title * {
    text-transform: none;
}
Brendan
  • 4,565
  • 1
  • 24
  • 39
  • My Script only capitalises the first letters. So this won't help. – Paul Mar 05 '12 at 17:01
  • The first letter of each word. The capitalise script does that. I want to use it to now capitalise only the first text node in div.title. – Paul Mar 05 '12 at 17:06
  • So, you want to capitalize the words in .title, but NOT the ones in .subtitle? – Brendan Mar 05 '12 at 17:09
  • yes as using text() on the div.title element will remove the subtitle div but will capitalise the text. Using html() encodes the '&' value which I don't want either. – Paul Mar 05 '12 at 17:16
3

You can use the replaceWith method http://jsfiddle.net/nEcSg/2/

You'll see that my example doesn't capitalize one of instances, namely <div class="subtitle">me & you</div>. I believe that is because your filter function is not finding the correct text nodes. Here's one thread on how to find text nodes How do I select text nodes with jQuery?. I think jQuery may not be the best way to do it

function capitalise(str) {
    if (!str) return;
    var stopWords = ['a', 'an', 'and', 'at', 'but', 'by', 'far', 'from', 'if', 'into', 'of', 'off', 'on', 'or', 'so', 'the', 'to', 'up'];
    str = str.replace(/\b\w+\b/ig, function(match) {
        return $.inArray(match, stopWords) == -1 ? match.substr(0, 1).toUpperCase() + match.substr(1) : match;
    }); 
    return str;
}

var fcn = $('div.title').contents().filter(function() { 
    return this.nodeType === 3;
}).replaceWith(function(){
    return capitalise($(this).text());
});

Working Answer

Based on the information on the post I linked above, I wrote something that works better. http://jsfiddle.net/nEcSg/3/

function capitalise(str) {
    if (!str) return;
    var stopWords = ['a', 'an', 'and', 'at', 'but', 'by', 'far', 'from', 'if', 'into', 'of', 'off', 'on', 'or', 'so', 'the', 'to', 'up'];
    str = str.replace(/\b\w+\b/ig, function(match) {
        return $.inArray(match, stopWords) == -1 ? match.substr(0, 1).toUpperCase() + match.substr(1) : match;
    }); 
    return str;
}

function getTextNodesIn(node, includeWhitespaceNodes) {
    var textNodes = [], whitespace = /^\s*$/;

    function getTextNodes(node) {
        if (node.nodeType == 3) {
            if (includeWhitespaceNodes || !whitespace.test(node.nodeValue)) {
                textNodes.push(node);
            }
        } else {
            for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                getTextNodes(node.childNodes[i]);
            }
        }
    }

    getTextNodes(node);
    return textNodes;
}


var textNodes = getTextNodesIn(document.body);
for (var i = 0; i < textNodes.length; i++) {
     var textNode = textNodes[i];
     textNode.parentNode.replaceChild(document.createTextNode(capitalise( $(textNode).text() ) ), textNode); 
}
Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217