XPages CSJS timing issue – what is ‘this’ ?

Problem

The JavaScript object represented by ‘this’ does not appear to be as expected.

The problem is caused because of the way that XPages adds events to DOM objects through the <xp:eventHandler>

The Situation

I wanted to pass the id from a button to a function. Outside of XPages I would normally acheive this by passing a reference to the button(this) to a function (saySomething in this case) and then extracting the id from the object passed:

function saySomething(obj){
	alert("This is my object - "+this
		+"nnThis is my id - "+
		this.id)
}
Describing 'this' when passed from a button to a function
Describing ‘this’ when passed from a button to a function
	<button id="markyButton" onclick="saySomething(this)"></button>

In this case I am passing the “this” object to the function.

this

is an object reference to the DOM element which it was generated from – for some serious stuff on ‘this’ check out this article

http://www.quirksmode.org/js/this.html

XPages fail ūüė¶

However when I add the JavaScript to the XPages button and add the code through the GUI Designer interface

Adding JavaScript through the XPages GUI
Adding JavaScript through the XPages GUI

I do not get the expected result when I click on the button……

Not what we expected
Not what we expected

The¬†Explanation…

The reason this happens is because of the way that XPages assigns events to objects in the webpage. If you have ever looked at the source of an XPages you will almost certainly have seen a whole load code like this at the end of the page

XSP.addOnLoad(function() {
XSP.attachEvent(".....
}

and this is how the XPage adds the event to the object – in the case of this example the XPages creates our button in the HTML but as you can see there is no onclick event initially assigned to it

		<button class="lotusBtn" type="button" name="view:_id1:_id2:_id37:button1" id="view:_id1:_id2:_id37:button1">Click This</button>

and then at the bottom of the web page source code we can see the assignment of the event after during the “addOnLoad” which means after the page has loaded.

<script type="text/javascript">

function view__id1__id2__id37__id40_clientSide_onclick(thisEvent) {
alert("This is my object - "+this+"nnThis is my id - "+this.id)

}

XSP.addOnLoad(function() {
XSP.attachEvent("view:_id1:_id2:_id37:_id40", "view:_id1:_id2:_id37:button1", "onclick", view__id1__id2__id37__id40_clientSide_onclick, false, 2);
});

</script>

What is happening?

The XPage is adding the¬†function “view__id1__id2__id37__id40_clientSide_onclick” to the “onclick” event of the “view:_id1:_id2:_id37:button1” DOM element (our button in this case).

The nuances of this are subtle but important – the code is not adding “alert(whetever)” to the onclick event it is adding a function call to the onclick event.

So. when the button is clicked the function¬†view__id1__id2__id37__id40_clientSide_onclick executes it’s code and in that situation ‘this’ no longer refers to the button.

The difference is clear when we look at the resulting code side by side

<button value="or Click this" id="button3" onclick='alert("This is my object - "+this+"nnThis is my id - "+this.id)'></button>

or

<button value="or Click this" id="button3" onclick='view__id1__id2__id37__id40_clientSide_onclick()'></button>

“this” is never passed to the view__id1__id2__id37__id40_clientSide_onclick() function and therefore any reference to the button is lost.

When the function executes – “this” refers to the function (which isn’t an object) and therefore we get the window (the webpage) as a failover.

The solution

If you need to do something like this then add the onclick event to the source pane.

Here is the XML markup for the XPages generated event (which fails me)

		<xp:button value="Click This" id="button1">
			<xp:eventHandler event="onclick" submit="false">
				<xp:this.script>
					<![CDATA[alert("This is my object - "+this+"\nThis is my id - "+this.id)]]>
				</xp:this.script>
			</xp:eventHandler>
		</xp:button>

and the XML markup  for the manually added onclick event (which works)

		<xp:button value="or Click this" id="button2"
			onclick='alert("This is my object - "+this+"\nThis is my id - "+this.id)'>
		</xp:button>

The demonstration

Here is a simple demo of the problem and the solution

Problem solved – I can’t submit my timesheet

Problem: I cannot submit my timesheet

At my company we use Deltek’s suite of CRM tools including Time and Expense. We have been getting help desk calls for users being unable to submit their time sheets. They have been intermittent and we have been unable to spot a pattern in browser usage or user type. I was assigned to the problem yesterday and this morning the helpdesk started lighting up with the issue.

Submitting my time sheet through Firefox did not work, but it worked using Internet Explorer. So that immediately discounts the possible cause of being 1) application is broken 2) network is causing the issue.

I do not have administrative access to the machine so there was only a limited number of things I could do from my desktop – So I loaded up my trusty HTTPFox plugin for Firefox to see if there was any issues with the POST or response. This is what I got back from the server when I hit Save…

<TITLE>ISAPI plug-in Error Message</TITLE><H2>Message from the ISAPI plugin:</H2><P>
Cannot write 2068 bytes to tmp file C:\WINDOWS\TEMP\_wl_proxy\_post_2656_119: GetLastError() 112
<HR><I>Build date/time: Apr 20 2009<I>
<P><HR><B>Change Number:</B> <I>1211636<BR>

This was sent to the Deltek helpdesk and their response was “It looks like a permission problem. I have encountered this issue before and I assigned full permission for all users on the c:\windows\temp\_wl_proxy directory of the IIS server.

So immediately I responded and said – nope it cannot be a permissions issue because that would not explain it being an intermittent problem. That is a scary solution to the problem and would merely mask any underlying issues if something was causing an authentication issue….

So what else would cause an inability to write to the server?

Is the disk full?

Answer: Yep Рthe C drive is full to capacity 

That makes complete sense because:

  • It is intermittent because Windows is trying to recycle temp space but cannot do it fast enough
  • It is worse in the morning because there are more people trying to hit it

 

Conclusion: Gather all the information possible before attempting to solve the problem and don’t always assume that the obvious answer is the correct one .