Showing posts with label ajax. Show all posts
Showing posts with label ajax. Show all posts

Saturday, May 3, 2008

GWT in-place-editor

The in place editor is one of the simplest yet powerful feature brought by Ajax.
I wrote two such editors last year, one using javascript and one leveraging Prototype as an exercise. Recently I started to study GWT more in depth and I found fun to write a GWT version of the in place editor.
I used the TextBox and Label widgets that will be used to display and edit the label.
The DeckPanel panel is used to alternate the display between the text box and the label widgets.
The interaction is performed using listeners. The ClickListener on the label copies the label value to the text box and switch the deck panel to show the text box. The KeyboadListener allows on the enter keystroke to copy the edited value to the label and switch back the deck panel to show the label.

public void onModuleLoad()
{
final DeckPanel deck = new DeckPanel();
final Label label = new Label("Initial Value");
final TextBox text = new TextBox();

// Wire the widgets
deck.add(label);
deck.add(text);
deck.showWidget(0);

//
label.addClickListener(new ClickListener()
{
public void onClick(Widget widget)
{
String value = label.getText();
text.setText(value);
deck.showWidget(1);
text.setFocus(true);
}
});

//
text.addKeyboardListener(new KeyboardListenerAdapter()
{
public void onKeyPress(Widget widget, char c, int i)
{
if (c == KEY_ENTER)
{
String value = text.getText();
label.setText(value);
deck.showWidget(0);
}
else if (c == KEY_ESCAPE)
{
deck.showWidget(0);
}
}
});

//
VerticalPanel vp = new VerticalPanel();
vp.add(deck);
RootPanel.get().add(vp);
}


The demo is available here.

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>