If you’ve ever had an issue with JavaScript running before the element you’re trying to manipulate on a SharePoint page has loaded, this post is for you. Rather than momentarily considering using something terrible like a setTimeout to delay execution, we can instead use an event that will let us know when the “body” of a SharePoint page (“body” in the MasterPage sense, not in the HTML markup sense) has finished loading.
OOB Functionality
Out of the box there’s an object called _spBodyOnLoadFunctionNames which is an array of function names to be run after the “body” element of the SharePoint page has loaded. Here’s how you make it work:
_spBodyOnLoadFunctionNames.push("FunctionName"); function FunctionName() { // Code alert("Page has loaded!"); }
And to do a function with parameters, you have to do:
_spBodyOnLoadFunctionNames.push("FunctionName"); function FunctionName() { FunctionWithParameters(“value1”,”value2”) ; } function FunctionWithParameters(param1, param2) { // Code alert("Page has loaded! param1: " + param1 + " param2: " + param2); }
I have no idea why they didn’t just make this an event that you could put a listener on, but this is better than nothing.
Creating a Real Event
To improve on this mediocre option, we can use jQuery to make a custom event that will fire when the page as loaded:
_spBodyOnLoadFunctionNames.push("SharePointBodyLoaded_TriggerEvent"); function SharePointBodyLoaded_TriggerEvent() { jQuery.event.trigger({ type: "SharePointBodyLoaded", message: "loaded", time: new Date() }); }
Now we just have to subscribe to the event, and we can use our classic jQuery format of providing an anonymous function:
jQuery(document).on("SharePointBodyLoaded", function () { // code alert('Page has loaded!'); });
I suggest making the event trigger code part of your core JavaScript any time you’re branding a SharePoint site, that way you can use subscribe to the event anywhere you need to, and don’t have to worry about multiple declarations.
UPDATE
After toying with this a bit more, you definitely have to be careful of your placement of this code, or your code might miss the event. You need to ensure that none of the event related code is inside a jQuery(document).ready block, or it has the potential to be loaded *after* the SharePoint event fires. I ran into an interesting issue where (in IE10) it would work fine when I refreshed the page, but hitting the page by navigating or using the address bar directly would cause my event trigger method to be added to the array *after* it had already been executed. For anyone else trying to troubleshoot timing issues, checking to see if _spBodyOnLoadCalled is true or false will tell you if the method that executes the items in the array has run already.
Note: In these examples you may notice that I’m using jQuery instead of the classic $, this is due to an occasional conflict on the $ variable in SharePoint… apparently they’re using some other library that wants to have that name. It doesn’t happen everywhere, but I find it best to avoid using the $ at all, so that I never have to worry about it conflicting with another library.Note: Thanks to SaurabhKV for his post on the original OOB functionality in the first half of this article.