Dev Notes

Notes on Development with Microsoft Technologies

JS Link: Avoid Polluting the Global Namespace

5 Comments

Over the past few months I have been doing a lot of research around JavaScript frameworks and techniques as I am learning how to create SharePoint 2013/O365 Apps for clients. A recent project had a need to override the default view of a few columns. JS Link proved to be the easiest way to accomplish the changes, but every example that I found had all of the JavaScript functions placed squarely in the global namespace. One of the things that I find seems to be common among all of the books and articles I have read over the past three months clearly states that we should do our due diligence to keep the global namespace in JavaScript as clean as possible.

Here’s a pretty good explanation over at StackOverflow. The answer discusses garbage collection as well as the dangers of placing everything in the global namespace. The common practice that I see is to wrap up your code into an immediately invoked function expression – if you study the basic code for a JS Link file, you’ll see that it makes use of an IIFE to get things rolling.

(function () {
	var override = {};
	
	override.Template = {};
	
	override.Template.Fields = {
		"Field": { 
			"View": function (ctx) {
					return ctx.CurrentItem.title + ": Overridden";
			}
		}; 
		
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(override);
)();

The IIFE creates a JavaScript line that is immediately executed when the script is loaded. In the example above, a new variable named override is created which will be a JavaScript object. A template property is attached along with a fields object containing the override behavior for the JS Link file. The JS Link, when executed will return the title of the list item with :Overridden appended. This template is registered with the TemplateManager in SharePoint.

The typical approach to creating JS Link files is to add a bunch of individual functions that are called by the JS Link IIFE.

(function() {
	var overrideCtx = {};
	overrideCtx.Templates = {};
	
	overrideCtx.Templates.Fields = {
		'Budget_x0020_ID': {'View': budgetIDField },
		'Actuals':{'View': actualsField },
		'Budget':{'View': budgetField }
	};
	
	SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function budgetIDField(ctx){
	var html = "<div><strong>" + ctx.CurrentItem.Budget_x0020_ID + "</strong></div>";
	return html;
}

function toUSD(number) {
	/* implementation of conversion to USD */
    return '$' + dollars + '.' + cents.slice(0, 2);
}

function actualsField(ctx) {
	var amount = ctx.CurrentItem.Actuals;
	return toUSD(amount);	
}

function budgetField(ctx) {
	var amount = ctx.CurrentItem.Budget;
	return toUSD(amount);
}

Technically, this is not incorrect, but it definitely adds additional functions to the global namespace that may not need to be there. To move this out of the global namespace means that an IIFE needs to be created. Additionally, a typical practice that I’m getting into is to create a namespace object for storing specific JavaScript functions for a client or solution.

First, I check to see if I already have an object to store my functions that are specific to this solution.

This line will check the global namespace for an object named AwesomeJSLinkSolution. If a variable with the same name is found, it is used. Otherwise a new object is created. (This is good and responsible use of the global namespace.)

Next, the IIFE declaration is created:

With the IIFE, anything that I want to be scoped publically, must be returned. This includes functions and variables that may need to be used later by the solution.

There is also a helper function called toUSD that is used by the solution. Since this function is not necessary to be called from outside the scope of the IIFE, it can be declared directly inside the IIFE. The final code for the IIFE now looks like the following:

var AwesomeJSLinkSolution = AwesomeJSLinkSolution || {};

AwesomeJSLinkSolution.BudgetFields = (function () {
	
	function toUSD(amount) {
		/* convert amount */
		return amount;
	};

	return {
		budgetIDField: function (ctx) {
			var html = "<div><strong>" + ctx.CurrentItem.Budget_x0020_ID + "</strong></div>";
			return html;
		},
		actualsField: function (ctx) {
			var amount = ctx.CurrentItem.Actuals;
			return toUSD(amount);	
		},
		budgetField: function (ctx) {
			var amount = ctx.CurrentItem.Budget;
			return toUSD(amount);
		}
	}
})();

Now the functions that apply to this specific solution are no longer located in the global namespace. Additionally, a function that is specific to this JS Link file is not even accessible outside of the IIFE.

The only outstanding task it to modify the JS Link file. This is a matter of simply updating the function calls to use the new object created by the IIFE.

(function() {
	var overrideCtx = {};
	overrideCtx.Templates = {};
	
	overrideCtx.Templates.Fields = {
		'Budget_x0020_ID': {'View': AwesomeJSLinkSolution.BudgetFields.budgetIDField },
		'Actuals':{'View': AwesomeJSLinkSolution.BudgetFields.actualsField },
		'Budget':{'View': AwesomeJSLinkSolution.BudgetFields.budgetField }
	};
	
	SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

The final file source is:

var AwesomeJSLinkSolution = AwesomeJSLinkSolution || {};

AwesomeJSLinkSolution.BudgetFields = (function () {
	
	function toUSD(amount) {
		/* convert amount */
		return amount;
	};

	return {
		budgetIDField: function (ctx) {
			var html = "<div><strong>" + ctx.CurrentItem.Budget_x0020_ID + "</strong></div>";
			return html;
		},
		actualsField: function (ctx) {
			var amount = ctx.CurrentItem.Actuals;
			return toUSD(amount);	
		},
		budgetField: function (ctx) {
			var amount = ctx.CurrentItem.Budget;
			return toUSD(amount);
		}
	}
})();

(function() {
	var overrideCtx = {};
	overrideCtx.Templates = {};
	
	overrideCtx.Templates.Fields = {
		'Budget_x0020_ID': {'View': AwesomeJSLinkSolution.BudgetFields.budgetIDField },
		'Actuals':{'View': AwesomeJSLinkSolution.BudgetFields.actualsField },
		'Budget':{'View': AwesomeJSLinkSolution.BudgetFields.budgetField }
	};
	
	SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

JS Link Resouces

Advertisements

Author: Chris Quick

I have been a developer of web based solutions since early 2001 delivering solutions to a wide array of organizations using ASP, ASP.NET and SharePoint. I was introduced to SharePoint in 2003 when the consulting firm I worked for at the time introduced it into the workplace. I began working with MOSS 2007 as soon as Microsoft released the RTM version in November 2006. The platform was implemented at the organization I worked for in 2007 and went live in March of that year. I was tasked with the administration and ongoing development of the platform. I currently work as a SharePoint Architect with Artis Consulting, developing solutions for a wide variety of business problems. The goal of this blog is to share my discoveries developing solutions with SharePoint. I welcome your comments and feedback to any post -- and I welcome suggestions for future topics.

5 thoughts on “JS Link: Avoid Polluting the Global Namespace

  1. Pingback: Handlebars + JSLink | SharePoint Dev Notes

  2. Pingback: Hosk’s Top CRM 2013 articles of the week 20th June 2014 - Hosk's Dynamic CRM 2011 Blog - Microsoft Dynamics CRM - Microsoft Dynamics Community

  3. Pingback: SharePoint 2013 and JavaScript–best practices | The SharePoint Grind

  4. Pingback: Hosk’s Top CRM 2013 articles of the week 20th June 2014 - Microsoft Dynamics CRM Community

  5. Pingback: Hosk’s Top CRM 2013 articles of the week 20th June 2014 | Hosk's Dynamic CRM Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s