ShowTable of Contents
Introduction
This article is part of the
XPages Extensibility API Developers Guide.
A Client Simple Action is an easy way for Developers to code a reusable piece of business logic (written in JavaScript) in an XPages application to be executed in the Web Browser when the associated event on a user interface component is fired.
Simple Actions are available in Domino Designer from a drop down list in the events tab for an XPages applications. There are Server and Client events. Server events execute when as request is made to the Server and is the actions associated with components are processed by the XPages Runtime, for example, an onclick event for a Submit button, or a PostQuerySave event on a Data Source.
In addition, any properties that are configurable for the Client Simple Action can be set in a property sheet for the Simple Action.
Background
In XPages (and JavaServer Faces) MethodBinding is an object that can be used to call a method on an instance of a Class that is identified by evaluatng the leading portion of a method binding expression (for example #{customerList.data} - where customerList is a reference to an instance of a managed bean (MyCustomerList) that contains a list of customers, and data, is mapped to the getData() method.
For XPages Client Simple Actions, the method should return the JavaScript code that represents the piece of business logic is to be executed in response to an event inthe Web Browser.
There are 3 key methods in for a method binding :-
- getExpressionString() return the expression String from which this MethodBinding was built.
- getType(FacesContext context) the Java class representing the return type from the method identified by this method binding
- invoke(FacesContext context, java.lang.Object[] params) the return value resulting from a call to the method identified by this method binding expression, passing it the specified parameters, relative to the specified FacesContext.
The XPages Extensibility API provides a Class to support building Client Side Action extensions.
1:
2: com.ibm.xsp.actions.client.AbstractClientSimpleAction
As Client Simple Actions return a String of JavaScript, getType() return String, so the is no need to override it.
Add a Dojo Effect Client Simple Action
As an example, the piece of business logic is a Dojo Fade Effect, in this case, there will be two, fadeIn and fadeOut. The handcoded JavaScript would be something similar to,
1:
2: var _id = dojo.byId("#{id:image1}");
3: var fadeArgs = {
4: node: _id
5: };
6: dojo.fadeIn(fadeArgs).play();
where node is the Web Browser DOM node to fade in. The fade out effect is almost identical, except that the dojo funciton name is fadeOut. Also, there are other argument for the faded effect that can be set, duration - how long the fade effect should take, and easing, the animation effect, i.e start fading slowly and then speed up, or vice versa.
Start be creating a Class to represent the Simple Action that extends AbstractClientSimpleAction.
1:
2: public abstract class AbstractFadeClientAction extends AbstractClientSimpleAction {
Then create variables to store the parameters the of the Client Simple action that
1:
2: private String _node; // The domNode or node id to fade
3: private Integer _duration; // How long, in milliseconds, should the fade take
4: private String _easing; // An easing function to apply to the effect
Create getters and setters to the
1:
2: public String getNode() {
3: if (_node == null) {
4: ValueBinding vb = getValueBinding("node");
5: if (vb != null) {
6: return (String) vb.getValue(FacesContext.getCurrentInstance());
7: }
8: }
9: return _node;
10: }
11:
12: public void setNode(String node) {
13: _node = node;
14: }
And do the same for duration and easing.
1:
2: public abstract String getFadeAction();
3: public abstract int getStartingOpacity();
4:
5: @Override
6: public Object invoke(FacesContext context, Object[] params)
7: throws EvaluationException, MethodNotFoundException {
8: /*
9: * Generate this.....
10: *
11: * dojo.style("#{id:image1}", "opacity", "0");
12: * var _id = dojo.byId("#{id:image1}");
13: * var fadeArgs = {
14: * node: _id
15: * };
16: * dojo.fadeIn(fadeArgs).play();
17: *
18: */
19: StringBuilder b = new StringBuilder(256);
20: String id = getNodeClientId(context,getNode());
21:
22: //dojo.style("#{id:image1}", "opacity", "0");
23: b.append("dojo.style(\"");
24: JSUtil.appendJavaScriptString(b, id); // #{id:<id>}
25: b.append("\", \"opacity\", \"");
26: b.append(Integer.toString(this.getStartingOpacity()));
27: b.append("\");\n");
28:
29: //var _id = dojo.byId("#{id:image1}");
30: b.append("var _id = dojo.byId(\"");
31: JSUtil.appendJavaScriptString(b, id); //#{id:image1}
32: b.append("\");\n");
33:
34: b.append("var fadeArgs = {\n");
35: b.append("node: _id\n");
36: b.append("};\n");
37: b.append("dojo." + this.getFadeAction() + "(fadeArgs).play();");
38:
39: return b.toString();
40: }
1:
2: /**
3: * Return the client id for a JSF component or generate an exception if it doesn't exist
4: */
5: protected String getNodeClientId(FacesContext context, String componentId) {
6: if(null != componentId && "" != componentId) {
7: // Look for a component in the JSF hierarchy
8: UIComponent c = FacesUtil.getComponentFor(getComponent(), componentId);
9: if(c!=null) {
10: return c.getClientId(context);
11: }
12: }
13: throw new FacesExceptionEx(StringUtil.format("Unknown component id {0} in client side simple action",componentId));
14: }
15: }
1:
2: package com.ibm.xsp.example;
3:
4: public class DojoFadeIn extends AbstractFadeClientAction {
5:
6: public String getFadeAction(){
7: return "fadeIn";
8: }
9:
10: public int getStartingOpacity(){
11: return 0;
12: }
13:
14: }
and create one for datre out,
1:
2: package com.ibm.xsp.example;
3:
4: public class DojoFadeOut extends AbstractFadeClientAction {
5:
6: public String getFadeAction(){
7: return "fadeOut";
8: }
9:
10: public int getStartingOpacity(){
11: return 100;
12: }
13:
14: }
1:
2: package com.ibm.xsp.example;
3:
4: import com.ibm.xsp.library.AbstractXspLibrary;
5:
6: public class SimpleActionExampleLibrary extends AbstractXspLibrary {
7:
8: public String getLibraryId() {
9: return "com.ibm.xsp.example.SimpleActionExampleLibrary.library";
10: }
11:
12: @Override
13: public String[] getFacesConfigFiles() {
14: return super.getFacesConfigFiles();
15: }
16:
17: @Override
18: public String getPluginId() {
19: return "com.ibm.xsp.simpleactionexample";
20: }
21:
22: @Override
23: public String getTagVersion() {
24: return "1.0.0";
25: }
26:
27: @Override
28: public String[] getXspConfigFiles() {
29: // TODO Auto-generated method stub
30: return new String[] {"META-INF/example-actions.xsp-config"};
31: }
32:
33: }
1:
2: <?xml version="1.0" encoding="UTF-8"?>
3: <faces-config>
4:
5: <!--
6: Define a new namespace for Demos.
7: -->
8: <faces-config-extension>
9: <namespace-uri>http://www.ibm.com/xsp/demo</namespace-uri>
10: <default-prefix>demo</default-prefix>
11: </faces-config-extension>
12:
13:
14: <group>
15: <group-type>com.ibm.xsp.example.simpleaction.client.dojo</group-type>
16: <property>
17: <description>Reference to the component</description>
18: <display-name>Node</display-name>
19: <property-name>node</property-name>
20: <property-class>java.lang.String</property-class>
21: </property>
22: <property>
23: <description>Easing</description>
24: <display-name>Easing</display-name>
25: <property-name>easing</property-name>
26: <property-class>java.lang.String</property-class>
27: </property>
28: <property>
29: <description>Duration</description>
30: <display-name>Duration</display-name>
31: <property-name>duration</property-name>
32: <property-class>int</property-class>
33: <property-extension>
34: <default-value>-1</default-value>
35: </property-extension>
36: </property>
37: </group>
38:
39: <complex-type>
40: <description>Apply a Dojo fade out effect to a component.</description>
41: <display-name>Dojo fade out effect</display-name>
42:
43: <complex-class>com.ibm.xsp.example.DojoFadeOut</complex-class>
44: <complex-id>com.ibm.xsp.example.FadeOut</complex-id>
45: <group-type-ref>com.ibm.xsp.example.simpleaction.client.dojo</group-type-ref>
46: <property>
47: <description>Ignore this Property</description>
48: <display-name>Ignore</display-name>
49: <property-name>ignore</property-name>
50: <property-class>int</property-class>
51: <property-extension>
52: <default-value>-1</default-value>
53: </property-extension>
54: </property>
55: <complex-extension>
56: <base-complex-id>simpleActionInterface</base-complex-id>
57: <tag-name>dojoFadeOut</tag-name>
58: <designer-extension>
59: <action-type>client</action-type>
60: <category>Demo Dojo Effects</category>
61: </designer-extension>
62: </complex-extension>
63: </complex-type>
64:
65: <complex-type>
66: <description>Apply a Dojo fade in effect to a component.</description>
67: <display-name>Dojo fade in effect</display-name>
68:
69: <complex-class>com.ibm.xsp.example.DojoFadeIn</complex-class>
70: <complex-id>com.ibm.xsp.example.DojoFadeIn</complex-id>
71: <group-type-ref>com.ibm.xsp.example.simpleaction.client.dojo</group-type-ref>
72: <property>
73: <description>Ignore this Property</description>
74: <display-name>Ignore</display-name>
75: <property-name>ignore</property-name>
76: <property-class>int</property-class>
77: <property-extension>
78: <default-value>-1</default-value>
79: </property-extension>
80: </property>
81: <complex-extension>
82: <base-complex-id>simpleActionInterface</base-complex-id>
83: <tag-name>dojoFadeIn</tag-name>
84: <designer-extension>
85: <action-type>client</action-type>
86: <category>Demo Dojo Effects</category>
87: </designer-extension>
88: </complex-extension>
89: </complex-type>
90:
91: </faces-config>