Tuesday, June 19, 2007

An implementation of partial portal page refresh

JBoss Portal 2.6 has partial page refresh for portlets feature.

The feature allows a page to be partially refreshed when a portlet link is clicked using ajax technology. The goal is not only to refresh the portlet markup but also ensure that the markup of the entire page is correct. And this of course should be totally transparent to the portlet code, i.e the portlet developer should not use an API other than JSR-168.

There is a lot of challenge when it comes to the implementation of that feature, both on the server side and on the client side. On the client side, it is to my opinion not trivial to come up with a universal solution. I built an implementation based on DOM events which allows to react on portlet clicks. I think also there are several other solutions and I have not investigated them all yet.

I choosed the DOM event based solution since it is the less intrusive because it does not require modifications of the portlet markup. It really helps to provide a solution which offers nice degradation when the client side has javascript disabled. It also works nicely with a portlet that would modify the DOM of their markup at runtime.

However I think there are some limitations that could always trigger a full refresh of the page. For instance the main limitation I see today is the programmatic submit of a form that never create events and therefore will force a full page refresh. It is possible to bypass that limitation in some browsers (Firefox, Safari and IE, I haven't yet tested other browsers).


<form id="my_form" action="/portal/...." method="post">

<select onclick="document.getElementById('my_form').submit()">
...
</select>

There is a workaround for this on browsers that allow to modify the prototype of DOM elements such as Firefox of Safari. It consist in modifying the prototype of the HTMLFormElement and replace the submit() method to perform the partial page refresh at this place.


var oldSubmit = HTMLFormElement.prototype.submit;
var newSubmit = function()
{
// Perform AJAX request and update here
}
HTMLFormElement.prototype.submit = newSubmit;

This technique does not work in IE (of course!!!), however it is possible to achieve the same result using a technique that emulates prototype behavior described below.


//This applies an IE "behavior" to the form elements

<style type="text/css">
form
{
behavior: url(test.htc);
}
</style>

And the IE behavior is


<method name="submit" internalname="_submit" />
<script type="text/javascript">
function _submit()
{
// Perform AJAX request and update here
}
</script>

No comments: