Thursday, July 05, 2007

Adding JavaScript to a Content Editor Web Part to Run onLoad


Adding JavaScript to a page inside a Content Editor web part can be a great way to perform on-the-fly customizations to your SharePoint sites. This worked great in WSS v2 and SPS 2003. We started noticing that some of those scripts didn’t seem to work in WSS v3 and MOSS 2007, however, and it wasn’t because the names of objects and elements had changed.
For example, here is a JavaScript snippet that we had used to hide the “NEW!” icon on a page in WSS v2.
Note: In all code examples below, replace the square brackets around the SCRIPT tags with angle brackets. If I included the angle brackets, the browser tried to execute the code. :o(
[script language="JavaScript"]
var fields,i;
fields = document.getElementsByTagName('IMG');
for( i = 0; i < fields.length; i ++ ) {
  var imgsrc = fields[i].getAttribute('SRC');
  if(imgsrc.indexOf("new.gif") != -1) { 
   fields[i].style.visibility = "hidden";
  }
}
[/script]
When we added this to a Content Editor web part in a WSS v3 page, nothing seemed to happen. I added code to make it run on the onLoad event, and that didn’t work either. I did a little experimentation and discovered that if I added a short delay, even a delay of 1/1000 of a second, it worked fine. I placed the core code within a function and then called it with the setTimeout() method.
[script language="JavaScript"]
setTimeout(HideNewIcons,1);
function HideNewIcons(){
  var fields,i;
  fields = document.getElementsByTagName('IMG');
  for( i = 0; i < fields.length; i ++ ) {
    var imgsrc = fields[i].getAttribute('SRC');
    if(imgsrc.indexOf("new.gif") != -1) { 
     fields[i].style.visibility = "hidden";
    }
  }
}
[/script]
The problem occurs because most WSS v3 pages use a master page that contains the “body” element, and the page content code loads after the master page code. I didn’t know it at the time, but recently discovered (thanks to this article on the Microsoft SharePoint Products and Technologies Team Blog) that the SharePoint developers had given us a way to work around that issue—it’s the _spBodyOnLoadFunctionNames array. We can use JavaScript’s “push” method to load items into this array where they will run when the body’s onLoad event fires .
Here is what the JavaScript looks like with the setTimeout replaced with a line that pushes the function name “HideNewIcons” into the _spBodyOnLoadFunctionNames array.
[script language="JavaScript"]
_spBodyOnLoadFunctionNames.push("HideNewIcons");
function HideNewIcons(){
  var fields,i;
  fields = document.getElementsByTagName('IMG');
  for( i = 0; i < fields.length; i ++ ) {
    var imgsrc = fields[i].getAttribute('SRC');
    if(imgsrc.indexOf("new.gif") != -1) { 
     fields[i].style.visibility = "hidden";
    }
  }
}
[/script]
If you’ve been having trouble getting some of your legacy JavaScript scripts to run from within Content Editor web parts in WSS v3 or MOSS 2007 pages, give this technique a try, and let me know if it works for you.

21 comments:

Anonymous said...

I think your first main paragraph of the text rather than the intro should say WSS 2.0 rather than WSS 3.0.

Could you re-check?

Mike Walsh

Ricky Spears said...

Mike - Good catch! I've fixed that to say, "here is a JavaScript snippet that we had used to hide the 'NEW!' icon on a page in WSS v2."

Anonymous said...

I've been trying to get code to execute by using _spBodyOnLoadFunctionNames.push("FUNCTION_NAME", but it doesn't seem to work. THe code is not gettting hit. I think I have the above statement in the wrong location. Do I have to add it within the context editor tags? If so, where? Could your show some sample code? Becuase when I try to add it within those tags, Sharepoint Designer closes with an error. Any help would be appreciated!!

Sally Alshazly said...

Hey Ricky, I'm having problems keeping the JS in pages in SharePoint. For some reason SharePoint keeps removing the JS. Any idea how to go around that?

Ricky Spears said...

Sally - My first guess is that your JavaScript uses a FORM. SharePoint will remove it if it does.

Anonymous said...

Hey I tried using the _spBodyOnLoadFunctionNames.push("function");
command - but moss 2007 still seems to remove the code.

Ricky Spears said...

Anonymous - It sounds like you are putting some custom code in your function that SharePoint doesn't like. Try using this method with a simpole function that just contains something simple, such as an ALERT. You'll see it does work. If SharePoint is removing your code, you'll just need to take our bits and pieces and work my trial and error to see what is causing the problems. Good luck!

Anonymous said...

Hi Ricky, I am having problems trying to add MIT's Simile Timeline widget(http://simile.mit.edu/timeline/) to my sharepoint site v3. Any suggestions?

Karen I said...

Ricky--this worked like a charm. Thanks a million!!

eli said...

Hi Ricky Im hoping you still might be checking this post. i am not sure what i am doing wrong and hope you can help. I am trying to show the value of a query string on the page (not a pop ) but im not sure what im missing. It seems to just not work in SPS/Wss. it just displays the onload code in the web part. this is the code i put into the content editor

[script language="JavaScript"]
_spBodyOnLoadFunctionNames.push("displayItem");
function displayItem(key){
if(queryString(key)=='false')
{
result.innerHTML="you didn't enter a ?name=value querystring item.";
}else{
result.innerHTML+=queryString(key)+"
";
}
}
[/script]
onload="displayItem('RootFolder'); displayItem('Folder');"

Ricky Spears said...

Eli - I think you have some problems in your JavaScript--you'll need to fix that on your own. I can help you with getting it to run when it's supposed to though.

You don't need to add the onload piece at all. It's displaying the code in the web part because it's outside the SCRIPT tags. To call the function twice and pass the two keys as you have indicated, just change the line that pushes it onto the _spBodyOnLoadFuncitonNames() Array to reflect that, like so:

_spBodyOnLoadFunctionNames.push("displayItem('RootFolder')");
_spBodyOnLoadFunctionNames.push("displayItem('Folder')");

Good luck!

polgara said...

Thanks a million!

I was having trouble with my Web Part for hours. I used your trick and it worked :)

Anonymous said...

Great article. I'm using it to do a global replace on some text that I don't want to show up on the page (specifically, in a list that is grouped by a category, I don't want to see the category name). It works perfect...except that it takes a second or two to apply, so the user sees the text for a second, then it goes away. Any way that you know of to fire this off before the page is painted? Thanks.

Anonymous said...

YOU R A LIFE SAVER.

Cant appreciate your tip more!

Thanks a lot....

Anonymous said...

I have used the _spBodyOnLoadFunctionNames.push to open a window on a mouseover event with success. However, I must be missing something as I am trying to control "style.display" for a couple of div elements on a page and cannot get it to work. Here is my code:

[script type="text/javascript" language="javascript"]
_spBodyOnLoadFunctionNames.push(“change_display1”);
_spBodyOnLoadFunctionNames.push(“change_display2”);

function change_display1() {
if (MyDiv1.style.display == ""){
MyDiv1.style.display = "none";}
else {
MyDiv2.style.display = "none";
MyDiv1.style.display = ""; }
}

function change_display2() {
if (MyDiv2.style.display == ""){
MyDiv2.style.display = "none";}
else {
MyDiv1.style.display = "none";
MyDiv2.style.display = ""; }
}

[/script]


[input type="button" value="Div 1" onClick="change_display1()"]


[input type="button" value="Div 2" onClick="change_display2()"]

[div id="MyDiv1" style="position:relative; display:none;"]
div info here
[/div]

[div id="MyDiv2" style="position:relative; display:none;"]
div 2 info here
[/div]

I get an 'Object expected' error when I click either of the buttons. If anyone can comment with a suggestion on what I am missing it would be greatly appreciated.
Regards,
DC

Josh said...

This is a great article. Someone mentioned above that the page loads, and then it takes a second or two, then reloads again. Is there a way to eliminate the delay? I am updating an iframe and the original iframe src is loaded, blinks for a second, and then loads the newly updated src property that I specifiy in my javascript.

murali said...

How to change Dynamically SPSite Template Default selection

Please Replay anybody for my issue still am not able to resolve this issue.

below code is working when i enable the alert statement(i.e if i remove alert stmt it showing default site template under that tab.

function setCustom()
{

var element = document.getElementById("ctl00_PlaceHolderMain_InputFormTemplatePickerControl_ctl00_ctl00_LbWebTemplate");
var tempname= document.getElementById("ctl00_PlaceHolderMain_TemplateName").value;
var tabs=tempname.split(';')
var tabslcid="1033&";
var getTemplates=tabslcid.concat(tabs[1]);
GetWebTemplates(getTemplates,tabs[0]);
var options = element.options;
var test = "false";
var count=0;
//alert(tabs[0]);
for (var i = 0; i < options.length; i++)
{
if (options[i].value == tabs[0])
{
options[i].selected = true;
return;
}

}
}
setTimeout("setCustom();", 200);

above code is working when i enable the alert statement(i.e if i remove alert stmt it showing default site template under that tab.

so how to do that. if you have any solution send me.

Thanks in Advaced

louisanravi said...

I'm having trouble getting the Delicious bookmark linkrolls to always appear in a Content Editor Web part (sometimes they do not load, sometimes they do). Can I use this technique with the linkroll javascript? How? I'm at the "cut & paste" level and don't know javascript very well. :-)

RW NightBlind said...

Hi

Thank you very much for this, works like a charm. Going to insert a Google map at www.uj.ac.za/contactuj. So watch the space!

Regards,
Werner

Witless Monkey said...

I have a requirement to add a World Clock at the top of the left zone on a Team Site. Somehow the code was preventing the drop-down nature of the top navigation bar. The _spBodyOnLoadFunctionNames.push(); function totally solved all my problems. Thanks a million.

Clem said...

Unfortunately this does not work in SharePoint 2010.