Question regarding themes

hi all,I have a theme that’s loading javascript libraries and css resources; some of those are loaded conditionally, based on the currently used browser client.

Now I would like to extend that and have some info regarding the user browser being displayed in the page header. My idea was to have the page body call a javascript function “onLoad”. What I tried so far was building a ViewBody control into my theme, trying to override the “afterPageLoad” event of the XPage. I so far succeeded in overriding various events of buttons (onclick) and edit boxes (onfocus), calling js functions or window.alert methods. But when I try to apply this to the ViewBody afterPageLoad event I receive nothing but but an error 500.

Is this probably the wrong object to treat? Or is it simply not possible to reach the page’s onLoad event?

As ever, any hint is welcome

Subject: XPages Theme: onLoad, output script, insight and example…

The .XSP tag, xp:view maps to the .HTML tag. The base themeID for the xp:view tag is ViewRoot. You have called out ViewBody as the themeID - please ensure you have set this themeID on your pages xp:view tag.

For the controls that you have effected the onclick event, these are client-side events. You are essentially defining the passthrough onclick attribute for the rendered HTML tag. This is quite different than the server-side XPage page events (beforePageLoad, afterPageLoad, etc). This events execute on the server-side, therefore document.write(), window.alert(), and any other client-side DOM JS calls do not apply.

Therefore, you are best to implement your solution using an Output script control (see figure below - find it under the “Other… Other controls…” section of the control library), with a themeID mapping into a theme declaration for that control, and a value property. The value (within the theme declaration) would contain the required client-side JS to write into your page header, add to the onload queue, etc. In doing so, you can leverage inline server-side JS that gets preprocessed within the value fragment.

eg:

  1. Theme Control declaration and definition
<name>browser.info.script</name>

<property>

   <name>value</name>

   <value>

    function getBrowserInfo(){

      // get the browser info using this

     // server-side JS preprocessed expression...

     var userAgentString = "#{javascript:context.getUserAgent().getUserAgent()}";

				

      // get the span i want to write into on page load...

      var computedField1 = XSP.getElementById("#{id:computedField1}");

      computedField1.innerHTML = "&lt;b&gt;" + userAgentString + "&lt;/b&gt;";

     }

			

     // run on page load queue...

     XSP.addOnLoad(getBrowserInfo);

   </value>

</property>
  1. .xsp markup with OutputScript control and themeId mapping back to .theme declaration
<?xml version="1.0" encoding="UTF-8"?>

<xp:view xmlns:xp=“http://www.ibm.com/xsp/core”>

<xp:scriptBlock

	id="scriptBlock1"

	themeId="browser.info.script">

</xp:scriptBlock>

<xp:text escape="true" id="computedField1"></xp:text>

</xp:view>

  1. Resultant .xsp page in the browser

FYI: Finding the Output script control…

Subject: Sorry, I don’t get it

Tony,

first of all many thanks for your input. It sounds promising but obviously there’s still a big knowledge gap for me to cross.

In your reponse you’re once talking about a xp:outputScript tag, then in your code example I can’t find it, but instead there’s a xp:scriptBlock control. I first tried xp:outputScript which resulted in an error inside eclipse. So I tried the scriptBlock control instead, but as soon as I had typed <xp:script my xsp editor completely went berserk, adding tons of code, replacing my freshly typed tag and finally crashing with a Java Nullpointer exception.

Next I carefully built an XML comment block, building the scriptBlock control inside it. Then, after I had removed the comment block, and everything had stayed calm, I built a .theme control code similar to the one you posted.

Result is disappointing:

MSIE7 simply does nothing but displaying the page as it was displayed before.

Firefox 3 did the same, but also came up with an error; Firebug reported a syntax error in some dojo library code…

I wonder if my mistake is in the interpretation of the special tags / controls you built into your XPage code…

Subject: See updated original post for more detail.

Subject: Hurray, works - well sort of…

Thanks a lot, especially for the update which made things a lot clearer for me.

Just one last hint: in trying carefully to follow all of your steps I copied most of your code. Which resulted in an error 500 in the browser. Reason was a variable declaration inside the theme’s node:

var computedField1 = XSP.getElementById…

Obviously this results in a conflict with the control of the same name. After changing the variable name to “compField” the example works perfectly!

Maybe you could alter your example once more…

And I’m sure it would make a good topic in the wiki, don’t you think?

Thanks again for helping!

[Updated an hour later]:

hmm, it worked for me in a brand new xpage. But then I tried to implement that into an existing page, and there it doesn’t work at all:

from firebug I can see that in the first simple test page there is a <script…> object right after the tag containing the code that was created locally inside the theme. This script-block however is missing completely in the other page. Instead there is another script block at the end of the page’s source, also containing a call to XSP.addonLoad, but that one is obviously created automatically by some XPage simple action.

Two more things I observed:

  1. I’m used to call my js functions WITH a set of brackets as in “getBrowserInfo()”, but in your code the function’s name is passed into the XSP.addOnLoad method without the brackets. And indeed: if I include them in the call my code breaks. If that’s the rule: why is it so and moreover, how wuold I pass arguments into such a function?

  2. I tried to move the function into a JS script library that is called as a resource in the header of the theme. But then again my code breaks.

After having read your last post and with the first successful steps I thought I had understood, but now I’m no longer sure about it :-((

Subject: miracle: it’s working now

really strange, same code, but two days later, and now it works as planned. This is not the first time something like that happened to me. Wonder how much cacheing is going on there…

Thanks anyway and again, that finally answered most of my questions!

Two (minor) topics remain however:

  1. why do we have to call functions without brackets here? Thus we can’t pass on args into the function. Or can we?

  2. why can’t we call functions from script libs bound into the theme as a resource?

Subject: dojo.addOnLoad with parameters

You can pass parameters by using a generic function:

dojo.addOnLoad(function(){ // yes, it must be called ‘function’ with no parameters;

myCustomFunction(a,b,c); // call whatever you want here;

alert(‘Kilroy is here!’); // you can do other stuff here too;

} // close function;

); //close addOnLoad;

Subject: Probably the wrong object…

Check the Wiki, it might have something. But I know that Dojo, for example, has other hooks to attach events to onLoad() – you shouldn’t call it directly.

Subject: agreed - in a real world scenario

You’re right, in a real application I wouldn’t really do that; dojo indeed could be an elegant solution, or I also could do some server-side scripting. At the moment, however, I’m in the process of preparing some technical workshops, and so am trying hard to figure out what CAN be done using themes (and it’s really amazing what can be accomplished here!).

Unfortunately, the wiki doesn’t reveal too much about themes, and neither do help or any other ressource I found so far.

But thanks for your input anyways.