PDA

View Full Version : title case with regular exp


larkin
05-23-2003, 04:04 PM
Does anyone know of a little script which will make the input in a textbox into title case (using regular expressions)? I don't want all uppercase or lowercase, I would like to make sure just the first letter of each word is capitalized, like in titles.

Ex. 'FERGUSON CONTRACTING' to 'Ferguson Contracting'

:confused: Any good help would be so much appreciated.

beetle
05-23-2003, 04:45 PM
Javascript's regular expressions don't have a transform capability, so it will actually be easier to do this w/o regex (I think)

String.prototype.toTitleCase = function()
{
var str = this.toLowerCase(),
newStr = '';

for ( var i = 0, l = str.length; i < l; i++ )
{
newStr += ( i == 0 || str.charAt( i - 1 ) == ' ' )?
str.charAt( i ).toUpperCase():
str.charAt( i );
}
return newStr;
}

var myStr = "FERGUSON CONTRACTING";
alert( myStr.toTitleCase() );

larkin
05-23-2003, 05:29 PM
That's pretty cool. Do you have any ideas about what I can do for common exceptions, like the D in MacDonald, the G in McGruff or the M in O'Malley? I thought of LeRoy too but I don't think I can do too much with that.

??

Jerome
05-23-2003, 05:35 PM
Make an Array with exceptions

Jerome

cheesebagpipe
05-23-2003, 05:48 PM
Recommended by Ferguson Contracting:

<input type="text" style="text-transform:capitalize;" onblur="this.value=this.value.toLowerCase()">

larkin
05-23-2003, 07:55 PM
These are good suggestions. Hopefully I can figure something out with this.

Thanks.

liorean
05-23-2003, 08:18 PM
Try something like this:
var sTitle=document.title.toLowerCase();
document.title=sTitle.replace(/\b(\w)/g,'$1'.toUpperCase());

beetle
05-23-2003, 08:28 PM
liorean - doesn't work. I tried that today knowing it wouldn't work - because I've tried it like a half-dozen times before and am always extremely frustrated that it does not. :mad:

Why? Because the transformation of $1 into the captured match happens AFTER the result of toUpperCase is returned - so you basically just uppercase the string "$1" - which doesn't change anything :(

liorean
05-23-2003, 08:38 PM
Argh!
Well, why not do this, then:var
aTitle=document.title.toLowerCase().split(/\b/g),
i=aTitle.length;
for(i-->0)
aTitle[i]=aTitle[i].slice(0,1).toUpperCase()+aTitle.slice(1);
document.title=aTitle.join(' ');

larkin
05-23-2003, 08:54 PM
Using the regular expression seems like it should work but nothing is happening for me.:(

Philip M
05-24-2003, 08:38 AM
If it is of interest, the following is what I have developed to format both names and address lines in my order form.

This covers names such as O'Reilly, McDonald, De'Ath, D'Arcy, Fotheringay-Smythe, and correctly formats the address with leading capitals and suitable spaces including PO Box 22 and C/o. Also covers punctuation idiosyncrasies and possessive apostophe in address lines (Hunter's Moon, St. Hilda's Road). Also 12th Street etc. And FPO (and BFPO).

May not be as elegant as some but it works! I'll bet someone comes up with an outlandish name (such as "ffoulkes") not covered!

A test line to try is: Haberdashers' Aske's School Old Girls' Association. (Multiple haberdashers and girls, only one Aske!)


function changeCase(addrline) {
var tmpStr = addrline.value.toLowerCase();

tmpStr = tmpStr.replace (/(\d+)([a-z]{3,})/gi, "$1 $2"); // add space after numbers when 3+ alphachars follow
tmpStr = tmpStr.replace (/\,/g, " "); // delete commas - replace by space (essential!)
tmpStr = tmpStr.replace (/(\d+)([.{2,}$])/gi, " $1$2"); // add 4 spaces before numbers not at end of string
tmpStr = tmpStr.replace (/(\S*)\"(\D+)\"(\S*)/g, '$1 "$2" $3'); // put spaces around "string" (force uppercase)
tmpStr = tmpStr.replace (/o\'/gi, "O' "); // change o' to O'+space (O' Reilly) (force uppercase)
tmpStr = tmpStr.replace (/(\s|\.)(mc)([a-z])/g, "$1mc $3"); // add space after Mc (force uppercase)
tmpStr = tmpStr.replace (/(\D)\./g, "$1. "); // add space after literal . (B. M. Smith > uppercase)
tmpStr = tmpStr.replace (/\-([a-z])/g, " - $1"); // add spaces around hyphens (force uppercase)
tmpStr = tmpStr.replace (/(^\s+)/, ""); // remove spaces at start of string
tmpStr = tmpStr.replace (/\s{4,}/g, " "); // remove excessive spaces > 4

if ((/fpo\b/.test(tmpStr)) || (/fpo\d/.test(tmpStr))) {
tmpStr = tmpStr.toUpperCase();
tmpStr = tmpStr.replace (/([A-Z])(\s{2,})/g, "$1 "); // remove spaces >1 between A-Z and A-Z/0-9 (not converse)
}

var SplitStuff = tmpStr.split(" ");
var ArrLen = SplitStuff.length;

for (var k=0; k<ArrLen; k++) {
var word = SplitStuff[k];
if (/\d/.test(word)) {word = word.toUpperCase()}
var wordLen = word.length;
var posn = word.search(/[a-zA-Z]/);
var firstChars = word.substring(0, posn+1).toUpperCase();
var postString = word.substring(posn+1,wordLen);
word = firstChars + postString;
word = word.replace ( /C\/O\b/g, "C\/o" );
word = word.replace ( /Po\b/g, "PO" );
word = word.replace (/\'a/, "'A"); // De'Ath and D'Arcy!

SplitStuff[k] = word;
}

var newline = SplitStuff.join(" ");
newline = newline.replace (/\.\s/g, "."); // re-format names B. M. Smith > B.M.Smith
newline = newline.replace (/Mc\s/,"Mc"); // reformat McXxxx
addrline.value = newline;
}


I am not sure but I thought Macdonald had no capital D, only a capital after Mc. If Leroy is important then I guess you can add him in as well as an exception - change Leroy to LeRoy. But there are LeFarge and similar which are tricky to handle. Obviously not every name starting with Le is LeSomething.

larkin
05-27-2003, 03:53 PM
This looks pretty useful. Thanks for the suggestions.

BenW
04-20-2005, 06:18 PM
Beetle's solution (I know, it's already more than a year old in the postings) is excellent! Thanks!

As expected, now I am trying to figure out how to write an array that would totally lowercase any prepositions in the title. Prepositions would be words such as "and," "or," "the."

I'm just stuck because my JavaScript skills could be stronger. Any ideas on how to rewrite Beetle's excellent code to include an array to force all prepositions to lowercase?? It's gotta be easy!

Thanks again!

Ben

Philip M
04-20-2005, 07:34 PM
I think the only way is to have a series of specific replacements
for prepositions and conjunctions after the script has raised all the first characters to upper case:

word = word.replace (/\sAnd\s/g, " and " );
word = word.replace (/\sThe\s/g, " the " );

... and so on

larkin
04-20-2005, 08:17 PM
Only for prepositions, doesn't do McDonald, etc.
Try this:

<script language=javascript>
var preparray = new Array(13);
preparray[0] = "and ";
preparray[1] = "the ";
preparray[2] = "for ";
preparray[3] = "to ";
preparray[4] = "in ";
preparray[5] = "a ";
preparray[6] = "at ";
preparray[7] = "from ";
preparray[8] = "by ";
preparray[9] = "an ";
preparray[10] = "or ";
preparray[11] = "if ";
preparray[12] = "of ";
preparray[13] = "up ";

String.prototype.toTitleCase = function()
{
var str = this.toLowerCase(),
newStr = '';

for ( var i = 0, l = str.length; i < l; i++ )
{
newStr += ( i == 0 || (str.charAt( i - 1 ) == ' ' && !IsPrep(str.substring(i))))?
str.charAt( i ).toUpperCase():
str.charAt( i );
}
return newStr;
}

function IsPrep(strP)
{
for(i=0;i<preparray.length;i++){
if(strP.indexOf(preparray[i]) == 0){
return true;
break;
}
}
return false;
}

var myStr = "FERGUSON OF THE LAKES CONTRACTING";
alert( myStr.toTitleCase() );

</script>

BenW
04-20-2005, 08:40 PM
This works beautifully! Thanks! Now, if only I could figure out exactly what the JavaScript is doing at each line. ... Time for me to break out my old JavaScript books and study this stuff again.

Hope I can return the favor sometime soon.

Mr.Perplexed
05-18-2005, 02:05 AM
I was battling with this one too and was convinced there had to be a way to change case whilst staying in reg exp land. Here's one option:

function titleCase(str) {
var strOut = "";
while ((/(\b\w)(\S+\s*)/g.exec(str)) != null)
strOut += RegExp.$1.toUpperCase() + RegExp.$2.toLowerCase();
return strOut;
}

var example = titleCase("The rain in Spain FALLS MAINLY IN the plain.")
// returns The Rain In Spain Falls Mainly In The Plain.

This uses the Regular Expression exec() method. When the supplied regular expression has the global flag set (the trailing /g), everytime you run exec() the global RegExp object is updated with the results for the current match.

You could prototype this function onto the String object as Beetle suggests in his post at the top of this thread (Aug 2002!).

gilesm
03-14-2006, 04:28 PM
String.prototype.toTitleCase = function()
{
return this.replace(/\b([a-z])/g,function($0){return $0.toUpperCase()});
}