Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

Exercise: Title Casing

Exercise 19 Average

Prerequisites for the exercise

  1. JavaScript String Methods
  2. All previous chapters

Objective

Create a function to convert a given string into title case.

Description

Consider the string 'This is great.'. If we are to convert this string into title casing in a naive way, we'd get the string 'This Is Great.'.

Title casing can be performed in a multitude of ways, some taking into account certain elements of English grammar such as prepositions and certain conjunctions. There is no universal title casing standard and so different implementations have different rules.

For us, we define title casing in a very naive way. That is, a string in title case is one where the first character of every word is in upper case.

As mentioned before, the string 'This Is Great.' is in title case. The words 'This', 'Is' and 'Great.' all have their first characters in upper case.

Note that here our definition of a word is simply a sequence of characters with a space on its left or its right. Hence, the string 'Superb stunt' constitutes two words whereas the string 'Awe-inspiring' constitutes just one word.

In this exercise, you have to create a function toTitleCase() that converts a given string into title case, as discussed above, and then returns it.

Your solution MUST NOT use any array methods.

Shown below are a handful of examples of the function's usage:

toTitleCase('This is great.')
'This Is Great.'
toTitleCase('An awe-inspiring story!')
'An Awe-inspiring Story!'
toTitleCase('10 tips to become successful')
'10 Tips To Become Successful'
toTitleCase('hello world!')
'Hello World!'
toTitleCase('HELLO WORLD!')
'HELLO WORLD!'
toTitleCase(' ')
' '
toTitleCase('')
''

Note the string 'HELLO WORLD!' here. It was already in upper case and hence there was no effect of converting it into title case.

Hints

Hint 1

Use the split() string method, with the delimiter ' ', to break the given string into an array of words.

Hint 2

Iterate over all words in the array obtained by splitting the given string, and then uppercase each word's first character.

Hint 3

In the end, join all the words in the array into a single string with a space character (' ') between them.

View Solution

New file

Inside the directory you created for this course on JavaScript, create a new folder called Exercise-19-Title-Casing and put the .html solution files for this exercise within it.

Solution

First, let's set up the basic structure of the function:

function toTitleCase(str) {
   // Code to go here.
}

Now, let's convert the given string str into a sequence of words (whose definition is given in the exercise's description above).

This can very easily be accomplished using the split() string method, passing in the string ' ' as the delimiter, as follows:

function toTitleCase(str) {
   var words = str.split(' ');
}

With the array of words in hand, what we ought to do next is to uppercase the first character of every word. This can be done by iterating over all the words and replacing each one with its corresponding first-character-uppercased version.

In the code below, we do exactly this:

function toTitleCase(str) {
   var words = str.split(' ');

   for (var i = 0, len = words.length; i < len; i++) {
      words[i] = words[i][0].toUpperCase() + words[i].slice(1);
   }
}
  • The first character of words[i], which is the current word in the loop, is accessed as words[i][0] and then uppercased using the method toUpperCase().
  • Then this uppercased character is concatenated with the remainder of the string, which is extracted with the help of the slice() method.
  • Finally, the result of the concatenation is written back to words[i].

Now, as the second-last step, we just need to join all the words in the array words using a space character in between them. That is, if words is ['A', 'B', 'C'], then we need to produce the string 'A B C', with a space between each of the words.

This also can be accomplished very simply using a for loop and an accumulator string variable meant to hold the concatenation of all words along with the space character, as demonstrated below:

function toTitleCase(str) {
   var words = str.split(' ');

   for (var i = 0, len = words.length; i < len; i++) {
      words[i] = words[i][0].toUpperCase() + words[i].slice(1);
   }

   var titleCasedStr = words[0];
   for (i = 1, i < len; i++) {
      titleCasedStr += ' ' + words[i];
   }
}

Perfect, so far.

The final thing left is to just return the string titleCasedStr. This is done below:

function toTitleCase(str) {
   var words = str.split(' ');

   for (var i = 0, len = words.length; i < len; i++) {
      words[i] = words[i][0].toUpperCase() + words[i].slice(1);
   }

   var titleCasedStr = words[0];
   for (i = 1; i < len; i++) {
      titleCasedStr += ' ' + words[i];
   }

   return titleCasedStr;
}

Seemingly, we might think that we've completed our function's definition, but that's not the case.

When the given string is '', the return value must ideally be ''. But, as of now, our toTitleCase() function doesn't return '' when it's passed in with ''. In fact, it returns nothing, but instead throws an error.

The snippet below illustrates this:

toTitleCase('')
Uncaught TypeError: Cannot read properties of undefined (reading 'toUpperCase') at toTitleCase (<anonymous>:5:30) at <anonymous>:1:1

The error message hints us that the problem lies in the line where the toUpperCase() method is invoked, and that is in line 5.

So what could be the problem there?

Well, when we split the empty string '' using the split() string method, we get back an array consisting of one single item, which is an empty string as well. That is, we get the array [''].

In the subsequent for loop (lines 4 - 6), when we access words[i][0], the expression words[i] resolves to '', and then words[i][0] resolves to undefined. Thereafter, accessing the toUpperCase() method on undefined throws an error.

Now the solution of this problem is to address the empty string string right at the start of the function. But still that won't solve all such problems. For instance, if we provide ' ' as the string, split() produces the array ['', ''], whereby there are two empty strings.

Therefore, a more generic, and a working, solution is to check if words[i] is '', and if it ain't, only then proceed with invoking the toUpperCase() method. And for this, we'll use the && operator.

Shown below is the complete definition of toTitleCase():

function toTitleCase(str) {
   var words = str.split(' ');

   for (var i = 0, len = words.length; i < len; i++) {
      words[i] = words[i] && words[i][0].toUpperCase() + words[i].slice(1);
   }

   var titleCasedStr = words[0];
   for (i = 1; i < len; i++) {
      titleCasedStr += ' ' + words[i];
   }

   return titleCasedStr;
}

Now, let's test this function:

toTitleCase('This is great.')
'This Is Great.'
toTitleCase('An awe-inspiring story!')
'An Awe-inspiring Story!'
toTitleCase('10 tips to become successful')
'10 Tips To Become Successful'
toTitleCase('hello world!')
'Hello World!'
toTitleCase('HELLO WORLD!')
'HELLO WORLD!'
toTitleCase(' ')
' '
toTitleCase('')
''

Voila! It works just as desired.