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\$
  • \$\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 '15 at 20:24
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>

| improve this answer | |
\$\endgroup\$
  • \$\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\$ – Michael McGriff Jan 15 '15 at 23:08
  • 2
    \$\begingroup\$ It misbehaves for names like Érica (which it converts to éRica). \$\endgroup\$ – Ismael Miguel Jan 16 '15 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 '15 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\$ – Ismael Miguel Jan 16 '15 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\$ – Ismael Miguel Jan 16 '15 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);.

| improve this answer | |
\$\endgroup\$

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