Click here to Skip to main content
Click here to Skip to main content

Composite Formatting with a JavaScript StringBuilder Implementation

By , 24 Sep 2008
 

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:

  • A string where the variables are replaced by an integer between semicolons (or format item), representing an index in an array
  • An array of objects

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:

  • arguments[0] will be the composite string
  • arguments[1] will be the value used to replace "{0}" in the composite string
  • arguments[2] will be the value used to replace "{1}" in the composite string
  • ...
  • arguments[n] will be the value used to replace "{n-1}" in the composite string

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 :

  • StringBuilder(string) (Constructor): initializes a new instance of the StringBuilder class and appends a string if passed.
  • append(string): appends a string, and returns the StringBuilder instance.
  • appendLine(string): appends a string in a new line and returns the StringBuilder instance.
  • appendFormat(string, arg1, arg2, ...): appends a string using Composite Formatting and returns the StringBuilder instance.
  • length(): returns the length of the string contained in the StringBuilder instance.
  • clear(): reinitializes the StringBuilder instance before returning it.
  • toString(separator): Returns the string contained in the StringBuilder by joining the appended strings using an optional separator.

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

  • 15th September, 2008: Initial post.
  • 19th September, 2008: Added string formatting option.
  • 20th September, 2008: Bugs corrected and source code added.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mohamed Attahri
Founder
France (Metropolitan) France (Metropolitan)
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralSimilar Article - "CustomFormat" - has conditional formatting that might improve localizationmemberScott Rippey22 Oct '09 - 8:00 
GeneralRe: Similar Article - "CustomFormat" - has conditional formatting that might improve localizationmemberMohamed Attahri26 Oct '09 - 7:20 
Questionwhat's the escape character of { or } ?memberanhchanghaudau18 Sep '08 - 19:13 
AnswerRe: what's the escape character of { or } ? [modified]memberMohamed Attahri18 Sep '08 - 23:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 24 Sep 2008
Article Copyright 2008 by Mohamed Attahri
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid