27
\$\begingroup\$

I got it working, all variations are displayed Sint-Anna as should be, but I wonder, is there a simpler way to this, since it looks very cluttered?

String.prototype.capitalize = function(){
    var sa = this.replace(/-/g,' ');
    var saa = sa.toLowerCase();
    var sb = saa.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } );
    var sc = sb.replace(/\s+/g, '-');
    return sc;
};

console.log('sint-anna'.capitalize());
console.log('sint anna'.capitalize());
console.log('sint-Anna'.capitalize());
console.log('Sint Anna'.capitalize());
console.log('SiNt anna'.capitalize());
console.log('SINT ANNA'.capitalize());

Console:

Sint-Anna
Sint-Anna
Sint-Anna
Sint-Anna
Sint-Anna
Sint-Anna

There are no ways that there is a wrong input like Si ntAn na resulting in Si-Ntan-Na.

\$\endgroup\$
1
  • \$\begingroup\$ I know you said javascript, and I'm a bit late, but you could also use CSS for this if it fits your needs. text-transform: capitalize works exactly how you want it. \$\endgroup\$
    – ZomoXYZ
    Oct 14, 2015 at 20:24

2 Answers 2

25
\$\begingroup\$

Your problem is an interesting one,but your solution is not a great use of regular expressions, since there's the better option of using the 'word boundary' anchor \b.

The boundary anchor matches a transition from a word, to a non-word, or vice versa. For this purpose, using the \w match to target word-characters after the \b is the right solution.

Note that the replace-function you give to the replace operation only needs the m argument now, there's no longer any sub-groups to process.

If your code was written as:

    String.prototype.capitalize = function(){
        return this.toLowerCase().replace( /\b\w/g, function (m) {
            return m.toUpperCase();
        });
    };

then you would convert-to-lowercase, then locate the first letter of any word, and convert that to uppercase.

Putting that in to action, like:

<body>
    <input id="myInput" type="text" value="" size="50" />
  
    <pre id="myOutput" style="background-color:lightgrey">type something in the box above</pre>
  
    <script>
      
        String.prototype.capitalize = function(){
            return this.toLowerCase().replace( /\b\w/g, function (m) {
                return m.toUpperCase();
            });
        };
      
        var myInput = document.getElementById('myInput');
        var myOutput = document.getElementById('myOutput')

        myInput.addEventListener('input', function(e) {
            myOutput.innerHTML = this.value.capitalize();
        });
    </script>

</body>

\$\endgroup\$
7
  • \$\begingroup\$ I noticed that this will capitalize the first letter of a word that comes after a symbol but not after a number. E.g. %asdf = %Asdf but 3asdf = 3asdf. Not sure if that's a problem but thought I'd mention it. \$\endgroup\$ Jan 15, 2015 at 23:08
  • 2
    \$\begingroup\$ It misbehaves for names like Érica (which it converts to éRica). \$\endgroup\$ Jan 16, 2015 at 0:25
  • \$\begingroup\$ @IsmaelMiguel - yes, it does, and I am reminded that JavaScript does not have unicode support for RegExes... and it just plain sucks. I'm trying to figure out how to change it (the expression), but it will be ugly. \$\endgroup\$
    – rolfl
    Jan 16, 2015 at 0:41
  • \$\begingroup\$ Try replacing /\b\w/ by /\b[\w\u00E0-\u00F6\u00F7-\u00FF]/ or /\b[\wà-öø-ÿ]/. You can check more UTF8 intervals here: utf8-chartable.de/unicode-utf8-table.pl?number=512 \$\endgroup\$ Jan 16, 2015 at 12:47
  • \$\begingroup\$ As a sidenote, you should change the <input type="textarea"> to <input type="text">. And using inline events is a bad things now-a-days. Use an event listener which is a lot better. Even field.oninput=function(){} is better than an inline handler. \$\endgroup\$ Jan 16, 2015 at 12:52
-1
\$\begingroup\$

The easiest way of making all the first letters uppercase in your array:

for (var i = 0 ; i < yourArray.length ; i++) {
    curTokens[i] = yourArray[i].charAt(0).toUpperCase()+yourArray[i].substr(1);
}
console.log(yourArray);

Every first character is taken using the charAt(0) and changed to uppercase using .toUpperCase(). We append the rest of the string using yourArray.substr(1);.

\$\endgroup\$

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