Learn about SharePoint 2013 development on Ted Pattison's Blog > Posts > Adding JavaScript code Behind a SharePoint 2010 Page
August 07
Adding JavaScript code Behind a SharePoint 2010 Page

I have written this blog post to cover a few essential topics for those who are new to Javascript or just getting started using JavaScript in a SharePoint 2010 environment. In particular, I am going to walk through three popular techniques for adding JavaScript code behind a page in a SharePoint 2010 site. For example, let's say you are working the the following minimal site page named Demo1.aspx which links to a JavaScript file named Demo1.js.

<%@ Page MasterPageFile="~masterurl/default.master" %>
asp:Content runat="server" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" >
<script src="Demo1.js" type="text/javascript"></script> </asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<h2>JavaScript Demo</h2>
<div id="div1">boring default content</div>
</asp:Content>

By placing the script element shown above in a asp:Content control which has a ContentPlaceHolderID attribute value of PlaceHolderAdditionalPageHead, you can force the browser to download and load in the JavaScript code that has been added to Demo1.js. For our first example, imagine the source file named Demo1.js contains the following JavaScript code which has been written to access the div element with the id of div1 and to dynamically update its content.

var div1 = document.getElementById("Div1");
div1.innerHTML = "Hello World" 

You will find that this JavaScript code does not work as expected. The problem is that JavaScript code written at top-level scope (aka global scope) is executed as soon as it downloads before the page has fully loaded. More specifically, this code executes before the browser has parsed the HTML elements of the page which means that it executes too early to access an HTML element such div1 using the Document Object Model (DOM). This results in the JavaScript code experiencing a runtime error with a message such as 'div1' is null or not an object.

The important observation here is that you need to way to delay the execution of your JavaScript code until the browser has parsed and loaded the page's HTML elements so they are accessible through the DOM. As you will see, there are several different ways to accomplish this.

Understanding the window.load event and Why You Can't Use it

The first technique I will describe is actually a technique you cannot use. It involves registering an event handler for the window.onload event handler. While you might see this technique in JavaScript books for beginners, I just want to make sure you understand why you should avoid using it when working with SharePoint 2010.

DOM provides a onload event on the window object. The important concept (at least in theory) is that this event fires after the pages has loaded at a time when your code can access HTML elements through the DOM. If you were adding code behind a simple HTML page that was not running in a SharePoint environment, you can add your code to a function with a name such as OnPageLoad and assign that function to the window.onload event property so it fires at the right time.

window.onload = OnPageLoad;

function OnPageLoad() {
  var div1 = document.getElementById("Div1");
  div1.innerHTML = "Hello world";
}

Throughout the history of JavaScript programming, assigning a function to the window.onload event in this simple fashion has never really worked for anything except the most trivial of Web sites. The first problem is that the browser will not execute the window.onload event as early as you would like. After the page has loaded the HTML elements and made them accessible through the DOM, the browser continues to delay the firing of the window.onload event until the page has also completed downloading other resources including large graphic images and Adobe Flash files. This results in a delayed execution that is often unacceptable.

The second issue is that only one function can be assigned to the window.onload event at a time. It requires some tricky JavaScript programming to register multiple functions to execute when the window.onload event fires. There has been many a time when the JavaScript code written by one programmer has unintentionally unregistered the windows.onload event handler written by another. What's more, the built-in JavaScript code that's automatically added to SharePoint 2010 pages usually assigns its own function to the windows.onload event which will effectively unregister any function you have registered.

Suffice to say, the window.onload event works much better in theory than in practice and you should not be using this technique to control the execution of your JavaScript code behind pages in a SharePoint 2010 environment. Now that I have covered what you shouldn't do, let's move on and discuss what you should do.

There are three different techniques you can use in SharePoint 2010 to wire up your code so it executes at the correct point of time just after the HTML elements on the page have become accessible through the DOM. These three techniques rely on three different JavaScript libraries which are (1) ASP.NET AJAX, (2) The SharePoint 2010 JavaScript Class Library and (3) The jQuery Library. Each of these libraries serve to extend the basic functionality available through the JavaScript language and the DOM and each provides it own solution to this problem. Here is a list of the three different techniques I will discuss and the JavaScript library used by each one.

  • Using the Sys.Application.add_load method made available by ASP.NET AJAX
  • Using the _spBodyOnLoadFunctionNames.push method made available by the SharePoint 2010 JavaScript Class Library
  • Using the document.ready event handler made available by jQuery.

Yes, you have three different choices so you must decide which one to use on a case by case basis. In many scenarios, any of the three will work just fine. Therefore, I will provide a little more detail on each technique and demonstrate the required syntax.

Using Sys.Application.add_load

The ASP.NET AJAX library is built into ASP.NET 3.5 and is automatically made available behind all pages in a SharePoint 2010 farm. There is no need for you to explicitly link to any additional JavaScript files. You can simply call the Sys.Application.add_load method to register a function that will execute right after the HTML elements on the page have been made accessible through the DOM. Since we're leveraging the ASP.NET AJAX library, we can also leverage the convenience of $get function in place of document.getElementById as well.

Sys.Application.add_load(OnPageLoad);

function OnPageLoad() {
  $get("div1").innerHTML = "Hello from ASP.NET AJAX";
}

Note that you can call the add_load method more than once if you need to register multiple functions. The ASP.NET AJAX library will execute each one of them in the order that they have been registered.

Using _spBodyOnLoadFunctionNames.push

In addition to the ASP.NET AJAX library, pages in a SharePoint 2010 environment also load in a set of JavaScript files for a JavaScript library which goes by the name of the SharePoint 2010 JavaScript Class Library. This library contains quite a few JavaScript files including one named init.js which contains a global variable named _spBodyOnLoadFunctionNames. This variable references an array of string values containing a list of method names that will be executed after the body of the page has loaded. You can register a function by passing its name as a string value to the push method of the global _spBodyOnLoadFunctionNames variable.

_spBodyOnLoadFunctionNames.push("OnPageLoad");

function OnPageLoad() {
  $get("div1").innerHTML = "Hello from ASP.NET AJAX";
}

The underlying mechanics which make this technique work are different than using the Sys.Application.add_load. If you examine any of the master pages that ship with SharePoint 2010, you will see that Microsoft has added the following onload attribute to the body element.

<body onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();" >

As you can see, the onload attribute has been configured with JavaScript code which calls the _spBodyOnLoadWrapper method from init.js. It is this call to _spBodyOnLoadWrapper which triggers the execution of all the functions that have been registered with a call to _spBodyOnLoadFunctionNames.push.

And now it's time for a quick tangential comment. If you are like me and you observe how the onload attribute on the body element works, you might be temped to experiment with the onload attribute on other HTML elements inside the body such as a div element to see if you can achieve similar results. Don't waste your time. It doesn't work. While the browser executes JavaScript code in the onload attribute of the body, it will ignore any JavaScript you add to onload attributes in other HTML elements such as a div element or a span element.

Using The document.ready Event Handler

The third technique relies on The jQuery Library and it is the technique that most Web designers and developers prefer if they are already using the jQuery library in their client-side development with SharePoint 2010. Note that this technique is different from the first two since it depends upon a library that is not automatically integrated into the pages in a SharePoint site. Therefore, you must explicitly link to one or more jQuery sources files from a master page or from the individual pages that use jQuery. You can read Deploying jQuery Library Source Files with a Feature if you need help getting started on linking to the required jQuery source files.

Now let's examine the jQuery code required to modify the contents of a div element on a page.

$(document).ready(OnPageLoad);

function OnPageLoad() {
  $("#div1").html("Hello from jQuery");
}

As you can see, there is a call to the jQuery function passing the DOM-based document object to obtain a jQuery wrapper. The jQuery wrapper for the document exposes the ready method which you can call passing your function to register it to execute it at the right time. This code listing also demonstrates how to create a jQuery wrapper object for the div element with the id of div1 and how to modify its content using the html method.

The jQuery mantra is write less, do more. jQuery lives up to its mantra by allowing you to pass your function directly to the jQuery function without having to explicitly deal with the document object or the ready method. The following code does the exact same thing as the previous listing because it has the effect of registering the OnPageLoad function with the ready event of the document object.

$(OnPageLoad);

function OnPageLoad() {
  $("#div1").html("Hello from jQuery");
}

Of course, if your goal is to be admitted to the jQuery cool kids club you can take things one step further. You can get rid of the OnPageLoad method altogether and move its code into an anonymous function. The following code has the exact same effect as the previous two listings.

$(function(){
$("#div1").html("Hello from jQuery");
});

Yes. this code has the same effect, yet it's faster to write and looks much cooler to the jQuery in-crowd. It also produces the desired effect of becoming completely unreadable to neophytes.

Summary

So, now you have seen three different ways of adding JavaScript code behind pages in a SharePoint 2010 site . All three techniques rely on some type of function registration to ensure that code execution is delayed until after the browser has created the HTML elements in the body of the page and they are accessible through the DOM. My personal preference is to use the last technique because I like to use jQuery whenever I can. However, you can fall back on the other two techniques in any scenario where the jQuery library is not being used.

Comments

There are no comments for this post.

© Copyright 2012 Ted Pattison.  |  All Rights Reserved
LOGIN