The difference between two methods of adding client-side JavaScript event-handling code to an XPages input control

There are two ways to add event handling client-side JavaScript code to an XPages input control. This post shows the difference in what is generated and a use case for when the less-obvious method can be useful.

The Scenario

I recently worked on an application designed for a touch screen interface where there are a lot of data entry fields.

In order to make it easier to use, I want it to automatically select the contents of a field when the field receives focus. This way, the user can easily change the value of a field without having to click into a field, select the contents, then delete the existing value and re-enter a new value.

If the contents can be automatically selected when the user sets the focus on a field, then the user can just start typing and it will replace the value.

It may not sound like much, but this is a significant improvement in usability on a touch screen, without using a mouse.

The JavaScript

This is a simple problem to solve on a standard web page. You can put this code on the onfocus event of a field to automatically select the contents:

this.select();

JavaScript Keyword: this

In JavaScript, the keyword this can be used to refer to the object receiving the event that has triggered the handler code.

This is very handy for getting the value of the current field or taking some other action on the field with a very compact syntax. In my case, I was trying to get a handle on the current field in order to select its contents.

Adding JavaScript via the Events View

The standard way to add client-side JavaScript event code is through the Events view. I went there and added the code to the client-side onfocus event.

JSEventCode_1

Here’s what the XPage source looks like:

<xp:inputText id="inputText1" value="#{document1.Field1}" defaultValue="--">
  <xp:eventHandler event="onfocus" submit="false">
    <xp:this.script><![CDATA[this.select();]]></xp:this.script>
  </xp:eventHandler>
</xp:inputText>

This is the HTML and JavaScript generated when the page is rendered:

...
<input type="text" value="--" id="view:_id1:inputText1" name="view:_id1:inputText1" class="xspInputFieldEditBox">
...
<script type="text/javascript">

function view__id1__id4_clientSide_onfocus(thisEvent) {
alert('Value: ' + this.value);
this.select();
}

XSP.addOnLoad(function() {
XSP.attachEvent("view:_id1:_id4", "view:_id1:inputText1", "onfocus", view__id1__id4_clientSide_onfocus, false, 2);
}); 

</script>

This is how client-side JavaScript is added on the XPage. It creates a function and runs code on page load to attach it to the event. In this case ‘this’ is not attached directly to the field.

When I click on the field (thus setting the focus and triggering the onfocus event), I see an error in firebug.

JSEventCode_1b_FirebugError

Workaround

There are ways to work around this limitation. If you add a unique class to the field or compute the client-side ID with pass-through EL syntax (“#{id:inputText1}”), you can get a handle to the field. But this is a little more effort that shouldn’t be necessary.

Adding JavaScript via the Properties View.

I noticed that there’s another place to add onfocus event code. If you click on the field and open the Properties view rather than the events view, you can go to All Properties > events > onfocus. Click on the icon in that field and you can enter JavaScript code.

JSEventCode_2

Code added this way is clearly managed differently than the standard event code. I noticed that code entered via All Properties doesn’t show up in the Events view and vice versa.

There’s a big difference in the output as well. Rather than the JavaScript function and code to attach it to the event handler, code entered this way is passed directly through to the generated input tag.

<input type="text" value="--" id="view:_id1:inputText2" name="view:_id1:inputText2" class="xspInputFieldEditBox" onfocus="this.select();">

This is exactly what I wanted to begin with!

And it works as expected.

Caveat

Since code entered this way is passed directly through, you cannot set it to execute a partial refresh (or trigger any other server side update directly). However, if you need a quick snippet of code that only needs to work with the client-side DOM, this is an option.

You can, however, still include pass-thru EL statements. You just have to realize that, since it’s putting the code directly into the client-side onfocus event, it will already be surrounded by double-quotes by default, so use single quotes instead and account for that.

Update: Handling this.select() in Chrome

It turns out that this.select() doesn’t work in Chrome. It briefly selects the text but immediately loses the selection.

There are two easy workarounds. (1) You can use the onclick event instead. (Tabbing into the field with the keyboard will automatically select the text anyway, so keyboard access is also covered.) (2) You can add return false; to the onmouseup event to allow it to work as well.

This sample field works in Chrome to select the contents when you click on the field:

<xp:inputText id="inputText1" defaultValue="myDefault"
  onfocus="this.select();" onmouseup="return false;">
</xp:inputText>
Advertisements

3 responses to “The difference between two methods of adding client-side JavaScript event-handling code to an XPages input control”

  1. Sven Hasselbach says :

    Another workaround is to use thisEvent.target instead of this in your event handler.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: