Tuesday, June 9, 2009

Adding JavaScript includes to all portal browsing pages

In almost every portal deployment, we usually have the need to create some JavaScript libraries that can be used by various components…possible functions could be window openers, url encoder/decoder or any other utility functions that you might not want to include in all your portlets.

Now, the question is: how do you add it to the portal page as (a) global include(s)? 2 possibilities:

  1. Add the JavaScript include(s) to the portal header/footer portlets (which is usually done in publisher, and displayed on all pages)
  2. Create a small UI customization that does the job more reliably.

You might have guessed it now: option 1 is not the one I am going to explain here. Why?

First, option 1 would not be worth a blog post since it is fairly easy to implement. But more seriously, depending on header or footer portlets is not reliable in order to include global resources. Indeed, different portlet headers/footers are displayed based on the current experience definition, and/or the current community you are in. Also, the header/footer portlet content can easily be modified (especially if implemented in publisher for example) which increase the chances of removing the resource include(s).

Ok, let’s dive into option 2!

By customizing the 2 main browsing portal DP (stands for Display Page) classes (MyPortalDP and GatewayHostedDP), you will be able to include all the JavaScript resource you need on virtually all end user portal pages: all portal community pages and on the gateway page in hosted display mode.

Luckily, those DP classes provide a method to override: DisplayJavaScriptFromChild. This method returns an HTMLScriptCollection object that will be read in order to add the JavaScript to the header tag (in between the portal <head></head> tags).

The following could be what you might want to have in this method override (it gets the list of JavaScript files to include from a Varpack, and iterate through this list in order to add it to the returned HTMLScriptCollection object)

protected override HTMLScriptCollection DisplayJavaScriptFromChild()
{
HTMLScriptCollection scriptCollection = base.DisplayJavaScriptFromChild();
try
{
//get all the JS to include
XPArrayList arrJSToInclude = ...Getting this from Varpack is a good idea, and as such, recommended...;
if(null != arrJSToInclude && arrJSToInclude.GetSize() > 0)
{
IXPEnumerator jsEnum = arrJSToInclude.GetEnumerator();
string src = "";
while(jsEnum.MoveNext())
{
src = (string)jsEnum.GetCurrent();
if(!"".Equals(src))
{
HTMLScript script = new HTMLScript(HTMLScript.TYPE_JAVASCRIPT);
src = src.Replace("pt://images/", ConfigHelper.GetImageServerRootURL(m_asOwner));
script.SetSrc(src);
log.Debug("Adding JS external file with src: {0}", src);
scriptCollection.AddInnerHTMLElement(script);
}
}
}
}
catch (Exception exc)
{
log.Error(exc, "An exception occurred while adding the custom javascript to the page head.");
}
return scriptCollection;
}


I never recommend customizing directly the portal classes...that way it is a bit simpler if you need to upgrade the portal version: you custom code is not everywhere.



So instead of customizing directly MyPortalDP and GatewayHostedDP, create new custom classes that inherit from those 2...then make sure your custom classes are loaded properly in the related Activity Spaces (PlumtreeAS and GatewayAS)...



Hope that is helpful!

No comments:

Post a Comment