I don't know if anyone is using my EventDelegation technique for custom events.
In case any of you do, I've updated the demo/script in the demoapp. You can now also delegate onChange events.
Showing posts with label server side event delegation. Show all posts
Showing posts with label server side event delegation. Show all posts
Monday, February 14, 2011
Thursday, December 2, 2010
New and improved EventDelegator with InViewEdit demo
In may 2010, I posted about server side event delegation. The demoapp was from my (current) point of view very messy and hard to use for any other purpose than the demo.
I've improved the EventDelegator code at work, and made it more general purpose. The client side script can be used for event delegation in the browser, or if you want to, use it in combination with server side event delegation.
On the client side, you should be able to delegate most events (I haven't implemented onChange).
This demoapp implements the same functionality as the previous, with a couple of additions. There's an edit icon on every editable area. When you click to edit a name, the field gets focus. If you press escape while in the field, the edit is cancelled, same as if you click the cancel button. The code is also a lot better documented through comments.
Here's the video from the previous app:
A screenshot from the new demoapp:

>> Download Demoapp
I've improved the EventDelegator code at work, and made it more general purpose. The client side script can be used for event delegation in the browser, or if you want to, use it in combination with server side event delegation.
On the client side, you should be able to delegate most events (I haven't implemented onChange).
This demoapp implements the same functionality as the previous, with a couple of additions. There's an edit icon on every editable area. When you click to edit a name, the field gets focus. If you press escape while in the field, the edit is cancelled, same as if you click the cancel button. The code is also a lot better documented through comments.
Here's the video from the previous app:
A screenshot from the new demoapp:

>> Download Demoapp
Labels:
server side event delegation,
xpages
Tuesday, April 27, 2010
XPages: Server Side Event Delegation - In view edit
This is a continuation of the previous investigation into the possibilities of Server Side Event Delegation (SSED).
As I mentioned at the end of the previous blogpost, the demoapp didn't take advantage of Client Side Event Delegation (CSED). This resulted in having to create the same amount of client side event listeners as was generated by the server. If you have repeat controls/view events, this can amount to quite a bit of script tags (html to download). The event listeners themselves can take up quite a bit of memory, and may make the page act a little sluggish.
Here's the generated script tags for events in this demoapp:
One for the global event delegator event handler, and one per link in the view pager. The view has thirty "click to edit" cells, and a couple of buttons from the previous version. Not bad. :)
The experiments into SSED is partially due to the aforementioned reasons, curiosity, and my eternal struggle to find smarter ways to work. Only time will show if it fulfills all of the above.
Since the previous experiment, the demoapp has grown a bit. I've added a couple of more class attributes:
The view has the delegate-click-parent class. This makes all the child elements with a class attribute of click-trigger activate the server side event delegator.
I created a custom column. This lets me put other controls into the column.
Inside the column, I put a panel, a field and a button. A cell is editable when a scoped variable containing unid is the same as the unid of the row that the cell belongs to.
The panel has a computed styleClass attribute. When the cell isn't editable, the panel acts as a click trigger. One of the class attributes is the previously mentioned data-class. This contains the unid of the row the cell belongs to. This unid is put into the previously mentioned scoped variable, making the cell editable.
The field has value="" and defaultValue="#{row.columnName}". This makes it possible to edit the field/have it take the value from the appropriate row/column. The field has a readonly attribute that's computed based upon if the cell is editable.
The button is hidden when the cell isn't editable. When clicked, it triggers a save and resets the editable row. The client side id of the button is passed along to the server. This makes it possible to get the name of the field/get the value from the params-map (contains all submitted values).
E.g.
component id of field/button -> field/button
client side id of button: view:_id1:button
client side id of field: view:_id1:field
No more than a simple replace to find the correct field name :)
That's more or less it. If this sounds like something interesting, take a look at the demoapp/code, and leave a comment if you're curious about something.
>> Download Demoapp
Share and enjoy!
As I mentioned at the end of the previous blogpost, the demoapp didn't take advantage of Client Side Event Delegation (CSED). This resulted in having to create the same amount of client side event listeners as was generated by the server. If you have repeat controls/view events, this can amount to quite a bit of script tags (html to download). The event listeners themselves can take up quite a bit of memory, and may make the page act a little sluggish.
Here's the generated script tags for events in this demoapp:
XSP.addOnLoad(function() {
XSP.attachPartial("view:_id1:eventDelegator", "view:_id1", null, "foo", ...
XSP.attachPartial("view:_id1:peopleView:pager1__Group__lnk__1", null, ...
XSP.attachPartial("view:_id1:peopleView:pager1__Group__lnk__2", null, ...
XSP.attachPartial("view:_id1:peopleView:pager1__Group__lnk__3", null, ...
XSP.attachPartial("view:_id1:peopleView:pager1__Group__lnk__4", null, ...
XSP.attachPartial("view:_id1:peopleView:pager1__Next", ...
});One for the global event delegator event handler, and one per link in the view pager. The view has thirty "click to edit" cells, and a couple of buttons from the previous version. Not bad. :)
The experiments into SSED is partially due to the aforementioned reasons, curiosity, and my eternal struggle to find smarter ways to work. Only time will show if it fulfills all of the above.
Since the previous experiment, the demoapp has grown a bit. I've added a couple of more class attributes:
- delegate-click-parent: makes a component a clickable area
- click-trigger: when parent has delegate-click-parent class/styleClass, elements with this class, when clicked, triggers the server side event delegator
- refresh-[refreshId]: previously refresh-target-[refreshId], the target of the partial refresh
- action-[name]: used by the server side event delegator to determine what action to take
- data-[value]: can be used on the server side for various things. E.g. unid of a row in a view
The view has the delegate-click-parent class. This makes all the child elements with a class attribute of click-trigger activate the server side event delegator.
I created a custom column. This lets me put other controls into the column.
Inside the column, I put a panel, a field and a button. A cell is editable when a scoped variable containing unid is the same as the unid of the row that the cell belongs to.
The panel has a computed styleClass attribute. When the cell isn't editable, the panel acts as a click trigger. One of the class attributes is the previously mentioned data-class. This contains the unid of the row the cell belongs to. This unid is put into the previously mentioned scoped variable, making the cell editable.
The field has value="" and defaultValue="#{row.columnName}". This makes it possible to edit the field/have it take the value from the appropriate row/column. The field has a readonly attribute that's computed based upon if the cell is editable.
The button is hidden when the cell isn't editable. When clicked, it triggers a save and resets the editable row. The client side id of the button is passed along to the server. This makes it possible to get the name of the field/get the value from the params-map (contains all submitted values).
E.g.
component id of field/button -> field/button
client side id of button: view:_id1:button
client side id of field: view:_id1:field
No more than a simple replace to find the correct field name :)
That's more or less it. If this sounds like something interesting, take a look at the demoapp/code, and leave a comment if you're curious about something.
>> Download Demoapp
Share and enjoy!
Thursday, April 22, 2010
XPages: Server Side Event Delegation
Update 27.04.10: I've updated the demoapp with In View Edit functionality
While working on a view with in view edit functionality today, I was appalled over how much client side code was generated.
I guess my subconsciousness was working on the problem, as I came up with a hack that lets you delegate events, while eating dinner (almost forgot the comma). It's somewhat similar to the event delegation that you would do in a browser. The current implementation has its definite limits, but I think it's a nice proof of concept.
Without the Programmatically Triggering an XPages Server Side Event Handler from a Client Side Script article by Jeremy Hodge, I don't think I would have come up with this hack, so thank you for sharing, Jeremy!
The short and simple explanation of the hack:
A global event handler is added to the XPage:
I use foo as the event name, so that the generated client side event handler has no possibility of being triggered.
I've added some client side JavaScript that acts upon elements with certain class attributes.
delegate-click: Clicks on an element with this class triggers the server event handler.
refresh-target-componentId: The component id of the control that should be updated.
The code could easily be extended to handle other events. Out of curiosity, I tested onmouseover and onfocus. Both work great.
When an event is triggered, param.$$xspsubmitvalue is set to the id of the component I want to update. As you can see in the above XPages source code snippet, the refreshId of the event is computed to this value. This means that only the requested component is updated. The eventDelegator-function that is triggered by the event uses also uses this value to determine what server side action should be executed.
In the attached demoapp, a viewScope value is altered depending on the refreshId. This toggles a couple of panels, which have computed their visibility based upon the scoped variable.
As for the limitations..
The component that is the target of the refresh has to be visible, as its generated id (clientId) is necessary to get the partial update to work.
This version of the hack doesn't do much about the problem of a lot of active event listeners for my "in view edit" problem. It only results in less generated code. To fix this, I'd have to make the client side code smarter. E.g. add client side event delegation. The container could have a delegate-child-clicks class. The children that should fire the events could have maybe have a click-trigger class. Anyways, that's for a future proof of concept.. :)
The reason I decided to post this experiment is that I hope that it can inspire other XPages developers to make something cool, as I feel Jeremy's post did for me.
Here's the demoapp for you to probe and inspect
Share and enjoy!
While working on a view with in view edit functionality today, I was appalled over how much client side code was generated.
I guess my subconsciousness was working on the problem, as I came up with a hack that lets you delegate events, while eating dinner (almost forgot the comma). It's somewhat similar to the event delegation that you would do in a browser. The current implementation has its definite limits, but I think it's a nice proof of concept.
Without the Programmatically Triggering an XPages Server Side Event Handler from a Client Side Script article by Jeremy Hodge, I don't think I would have come up with this hack, so thank you for sharing, Jeremy!
The short and simple explanation of the hack:
A global event handler is added to the XPage:
<xp:eventHandler id="eventDelegator" event="foo"
action="#{javascript:delegateEvent()}" submit="true" refreshMode="partial"
refreshId="#{javascript:param.$$xspsubmitvalue}" />I use foo as the event name, so that the generated client side event handler has no possibility of being triggered.
I've added some client side JavaScript that acts upon elements with certain class attributes.
delegate-click: Clicks on an element with this class triggers the server event handler.
refresh-target-componentId: The component id of the control that should be updated.
The code could easily be extended to handle other events. Out of curiosity, I tested onmouseover and onfocus. Both work great.
When an event is triggered, param.$$xspsubmitvalue is set to the id of the component I want to update. As you can see in the above XPages source code snippet, the refreshId of the event is computed to this value. This means that only the requested component is updated. The eventDelegator-function that is triggered by the event uses also uses this value to determine what server side action should be executed.
In the attached demoapp, a viewScope value is altered depending on the refreshId. This toggles a couple of panels, which have computed their visibility based upon the scoped variable.
As for the limitations..
The component that is the target of the refresh has to be visible, as its generated id (clientId) is necessary to get the partial update to work.
This version of the hack doesn't do much about the problem of a lot of active event listeners for my "in view edit" problem. It only results in less generated code. To fix this, I'd have to make the client side code smarter. E.g. add client side event delegation. The container could have a delegate-child-clicks class. The children that should fire the events could have maybe have a click-trigger class. Anyways, that's for a future proof of concept.. :)
The reason I decided to post this experiment is that I hope that it can inspire other XPages developers to make something cool, as I feel Jeremy's post did for me.
Here's the demoapp for you to probe and inspect
Share and enjoy!