Click here to Skip to main content
Email Password   helpLost your password?

Introduction

If you're a .NET developer, you must know how useful the StringBuilder class can be. I found this excellent article named JavaScript String Builderby K. Collins, and while the performance issues related to string concatenations were solved, I found myself missing a very neat feature of the .NET Framework: Composite Formatting.

Understanding Composite Formatting

Composite formatting allows you to separate the "static" string elements from the "variable" ones, marking it much more readable, specifically when dealing with complex and long string concatenations.

Basically, composite formatting requires two arguments:

The composite formatting function will replace the format item {n} by the string representation of the nth element in the provided array.

A string representation is obtained by calling the toString function (built-in every object in JavaScript).

It’s very common to pass an argument to it to customize the output. You can specify this argument by adding it right after the integer in the format item, preceded by colon. It should look like this : {n:format}.

The JavaScript Implementation

Instead of implementing a function with two parameters, I thought about using the arguments property of the JavaScript function to avoid having to explicitly pass the array of values as an Array object.

In JavaScript, the arguments property is available inside functions and contains all the arguments passed to the function being executed.

In our case:

I'm directly extending K. Collins' StringBuilder, but the code can easily be used to extend any other object with composite formatting. I'm assuming you're familiar with RegExp and Regular Expressions.

 	//Storing the RegExp as a constant
	//to avoid initializing a new instance at each call.
	StringBuilder.prototype.CompositeFormattingRegExp = 
             new RegExp(/{\d+}|{\d+:[^\r\n{}]+}/g);


	//Appends a string using Composite Formatting 
	StringBuilder.prototype.appendFormat = function() { 
	//the first argument is the composite string 
	var Result = arguments[0]; 

	//looping through Result 
	//replacing each {n} with arguments[n+1] 
	var RegExpResult = null; 
	while ((RegExpResult = CompositeFormattingRegExp.exec(Result)) != null) { 

		//RegExp.exec doesn't return a string, 
		//type conversion is necessary 
		RegExpResult = RegExpResult.toString(); 

		//extracting the index, 
		//and the formatting string 
		var ColonsPosition = RegExpResult.indexOf(":"); 
		var paramIndex = -1; 
		var paramFormat = ''; 

		if (ColonsPosition != -1) { 
			paramIndex = new Number(RegExpResult.substr(
                               1, ColonsPosition - 1)); 
			paramFormat = RegExpResult.substr(ColonsPosition + 1,
                               RegExpResult.length - 2 - ColonsPosition); 
		} 
		else { 
			paramIndex = new Number(RegExpResult.substr(1,
                               RegExpResult.length - 2)); 
		} 

		//replacing the format item in Result string
		paramIndex++;
		var Replacement = (
                      ColonsPosition != -1) ? arguments[paramIndex].toString(paramFormat) :
                      arguments[paramIndex].toString(); 
		Result = Result.replace(RegExpResult, Replacement); 
	
		//g Flag makes RegExp remember the last position, 
		//we're updating it because directly we're modifying 
		//the string we're using the perform the search 
		CompositeFormattingRegExp.lastIndex += Replacement.length -
                      RegExpResult.length; 
	};

	//appending the formatted string to the StringBuilder 
	this.append(Result); 
};

Example of Use

The source zip file above contains a ready-to-use StringBuilder class (a compressed version is included for production use). The following methods are what you need to know to start using it :

Please note that methods related to appending strings are built using the chainability principle (jQuery-like), meaning : Every method within StringBuilder returns the object itself, allowing you to 'chain' upon it.

//Overriding the Number.toString function to support custom formatting
Number.prototype.toString = function(format) { 
	switch(format) {
		case "money":
			return "$" + this;
		case "surface":
			return this + "m²";
		default:
			return this.toLocaleString();
	}
}

// create a StringBuilder
var sb = new StringBuilder("Initializing a new instance")
.appendLine("append text in a new line")
.appendLine("")
.appendFormat("appending text using composite formatting : {0:money}, {1:surface}, {2},
    {{3}}", 100, 200, 300, 400);

// get the full string value
var s = sb.toString();

Versions

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralSimilar Article - "CustomFormat" - has conditional formatting that might improve localization
Scott Rippey
9:00 22 Oct '09  
I wrote an article about Custom Formatting in .NET, and I think some of the techniques I used are pretty similar to yours.
I've considered creating a JavaScript version of the CustomFormat function, because it really makes it easy to create "natural language" strings, and allows custom formatting to be done on any type.
If you want to take a look, the article is here: Custom Formatting in .NET - Enhancing String.Format to all new levels![^]
Among the many features, my favorite is Conditional Formatting, which allows easy localization and allows formatting rules to be right in the string template. It's best described with an example.
result = CustomFormat("There {0:is|are} {0} {0:item|items} remaining...", items.Count)

I think some of my techniques and syntax could be way easier to implement in a JavaScript version because of the ease of (or lack of) "reflection" and evaluating string expressions.
GeneralRe: Similar Article - "CustomFormat" - has conditional formatting that might improve localization
Mohamed Attahri
8:20 26 Oct '09  
You know what, I was looking for a solution to this problem. I spend hours adding inline if-then-else's.

I'm going take a look at it and will very likely extend my previous work with your enhancements.

Thanks again, I'll keep you posted.

Mohamed Attahri

Generalwhat's the escape character of { or } ?
anhchanghaudau
20:13 18 Sep '08  
I want to format "{0},{1}" to "{value1},{value2}", but nothing happens
AnswerRe: what's the escape character of { or } ? [modified]
Mohamed Attahri
0:03 19 Sep '08  
You no longer need to use escape characters. I managed to make it as simple as doubling the semicolons.


.appendFormat("{{0}} , {{1}}", "value0", "value1");



Hi,

the escape character when using RegExp is backslash "\".

try this :


appendFormat("\{{0}\},\{{1}\}", "value0", "value1");


Thank you.


Mohamed Attahri

modified on Tuesday, September 30, 2008 8:30 AM


Last Updated 24 Sep 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010