Author: nbelaevski
Date: 2009-08-25 12:34:42 -0400 (Tue, 25 Aug 2009)
New Revision: 15297
Modified:
root/examples/trunk/components/core-demo/src/main/webapp/function.xhtml
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/AjaxComponent.java
root/framework/trunk/impl/src/main/java/org/ajax4jsf/renderkit/AjaxRendererUtils.java
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces-jsf-log.js/4_0_0.js
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces.js/4_0_0.js
root/ui/trunk/components/core/src/main/java/org/richfaces/component/html/HtmlAjaxFunction.java
Log:
Added begin/beforedomupdate/complete events support
Modified: root/examples/trunk/components/core-demo/src/main/webapp/function.xhtml
===================================================================
--- root/examples/trunk/components/core-demo/src/main/webapp/function.xhtml 2009-08-25
15:54:16 UTC (rev 15296)
+++ root/examples/trunk/components/core-demo/src/main/webapp/function.xhtml 2009-08-25
16:34:42 UTC (rev 15297)
@@ -29,6 +29,10 @@
<f:param name="idsToRender" value="time2" />
</a4j:jsFunction>
+ <a4j:jsFunction name="eventsBoundFunction" status="someStatus"
onbegin="alert(event.type + ' begin')" oncomplete="alert(event.type
+ ' complete')" onbeforedomupdate="alert(event.type + '
beforedomupdate')">
+ <f:ajax event="complete" />
+ </a4j:jsFunction>
+
<h:commandLink value="test">
<f:ajax />
<f:param name="a" value="b" />
@@ -39,6 +43,7 @@
<a href="javascript:testFunction1Limited()">Call test function1 with
limitRender=true</a>
<a href="javascript:testFunction2()">Call test function2</a>
<a href="javascript:testFunction2Limited()">Call test function2 with
limitRender=true</a>
+ <a href="javascript:eventsBoundFunction()">Call events bound
function</a>
<a4j:log />
</h:body>
</f:view>
Modified:
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/AjaxComponent.java
===================================================================
---
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/AjaxComponent.java 2009-08-25
15:54:16 UTC (rev 15296)
+++
root/framework/trunk/api/src/main/java/org/ajax4jsf/component/AjaxComponent.java 2009-08-25
16:34:42 UTC (rev 15297)
@@ -90,8 +90,6 @@
*/
public abstract String getOncomplete();
-
-
/**
* @return value or result of valueBinding of Name of JavaScript function, called
before updating DOM
*/
@@ -102,6 +100,10 @@
* @param new value of Name of JavaScript function, called before updating DOM to
set
*/
public abstract void setOnbeforedomupdate(String beforeUpdate);
+
+ public abstract String getOnbegin();
+
+ public abstract void setOnbegin(String onbegin);
/**
* setter method for property
Modified:
root/framework/trunk/impl/src/main/java/org/ajax4jsf/renderkit/AjaxRendererUtils.java
===================================================================
---
root/framework/trunk/impl/src/main/java/org/ajax4jsf/renderkit/AjaxRendererUtils.java 2009-08-25
15:54:16 UTC (rev 15296)
+++
root/framework/trunk/impl/src/main/java/org/ajax4jsf/renderkit/AjaxRendererUtils.java 2009-08-25
16:34:42 UTC (rev 15297)
@@ -99,6 +99,7 @@
*/
public static final String ONBEFOREDOMUPDATE_ATTR_NAME = "onbeforedomupdate";
+ public static final String ONBEGIN_ATTR_NAME = "onbegin";
/**
* Attribute to keep
@@ -287,6 +288,31 @@
}
}
+ private static enum EventOptionsData {
+ begin {
+ @Override
+ public String getAttributeValue(UIComponent component) {
+ return getAjaxOnBegin(component);
+ }
+ },
+
+ beforedomupdate {
+ @Override
+ public String getAttributeValue(UIComponent component) {
+ return getAjaxOnBeforeDomUpdate(component);
+ }
+ },
+
+ complete {
+ @Override
+ public String getAttributeValue(UIComponent component) {
+ return getAjaxOncomplete(component);
+ }
+ };
+
+ public abstract String getAttributeValue(UIComponent component);
+ }
+
public static AjaxEventOptions buildEventOptions(FacesContext facesContext,
UIComponent component) {
@@ -296,9 +322,40 @@
if (ajaxStatusName != null && ajaxStatusName.length() != 0) {
ajaxEventOptions.set(STATUS_ATTR_NAME, ajaxStatusName);
}
+
+ Map<String, Object> parametersMap = new LinkedHashMap<String, Object>();
+ appendParameters(facesContext, component, parametersMap);
+ ajaxEventOptions.getParameters().putAll(parametersMap);
- appendParameters(facesContext, component, ajaxEventOptions.getParameters());
+ Collection<Parameter> behaviorParametersList = null;
+ Map<String, List<ClientBehavior>> behaviorsMap = Collections.EMPTY_MAP; /*
null object */
+
+ if (component instanceof ClientBehaviorHolder) {
+ ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder) component;
+ behaviorsMap = clientBehaviorHolder.getClientBehaviors();
+ }
+ for (EventOptionsData eventOptionsData : EventOptionsData.values()) {
+ String behaviorName = eventOptionsData.toString();
+ ClientBehaviorContext behaviorContext = null;
+ List<ClientBehavior> behaviorsList = behaviorsMap.get(behaviorName);
+ if (behaviorsList != null) {
+ if (behaviorParametersList == null) {
+ behaviorParametersList = getBehaviorParametersList(facesContext, component,
parametersMap);
+ }
+
+ behaviorContext = ClientBehaviorContext.createClientBehaviorContext(facesContext,
component,
+ behaviorName, null, behaviorParametersList);
+ }
+
+ String behaviorsChain = createBehaviorsChain(facesContext,
eventOptionsData.getAttributeValue(component),
+ behaviorsList, behaviorContext, false);
+
+ if (isNonEmpty(behaviorsChain)) {
+ ajaxEventOptions.set(behaviorName, behaviorsChain);
+ }
+ }
+
return ajaxEventOptions;
}
@@ -727,6 +784,13 @@
return (String) component.getAttributes().get(ONBEFOREDOMUPDATE_ATTR_NAME);
}
+ public static String getAjaxOnBegin(UIComponent component) {
+ if (component instanceof AjaxComponent) {
+ return ((AjaxComponent) component).getOnbegin();
+ }
+
+ return (String) component.getAttributes().get(ONBEGIN_ATTR_NAME);
+ }
/**
* Calculate, must be component render only given areas, or all sended from
@@ -1160,10 +1224,8 @@
return result;
}
- public static Collection<ClientBehaviorContext.Parameter>
getBehaviorParametersList(FacesContext context, UIComponent component) {
- Map<String, Object> parametersMap = new LinkedHashMap<String, Object>();
- //TODO: merge to a single method
- appendParameters(context, component, parametersMap);
+ private static Collection<ClientBehaviorContext.Parameter>
getBehaviorParametersList(FacesContext context, UIComponent component,
+ Map<String, Object> parametersMap) {
List<Parameter> result = new
ArrayList<ClientBehaviorContext.Parameter>(parametersMap.size());
for (Map.Entry<String, Object> entry : parametersMap.entrySet()) {
@@ -1171,4 +1233,12 @@
}
return result;
}
+
+ public static Collection<ClientBehaviorContext.Parameter>
getBehaviorParametersList(FacesContext context, UIComponent component) {
+ Map<String, Object> parametersMap = new LinkedHashMap<String, Object>();
+ //TODO: merge to a single method
+ appendParameters(context, component, parametersMap);
+
+ return getBehaviorParametersList(context, component, parametersMap);
+ }
}
Modified:
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces-jsf-log.js/4_0_0.js
===================================================================
---
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces-jsf-log.js/4_0_0.js 2009-08-25
15:54:16 UTC (rev 15296)
+++
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces-jsf-log.js/4_0_0.js 2009-08-25
16:34:42 UTC (rev 15297)
@@ -52,17 +52,16 @@
var log = richfaces.log;
var source = data.source;
- var status = data.status;
var type = data.type;
var responseCode = data.responseCode;
var responseXML = data.responseXML;
var responseText = data.responseText;
- if (type == 'event') {
- log.info("Received '" + status + "' event from " +
identifyElement(source));
+ if (type != 'error') {
+ log.info("Received '" + type + "' event from " +
identifyElement(source));
- if (status == 'complete') {
+ if (type == 'beforedomupdate') {
var partialResponse;
if (responseXML) {
@@ -78,17 +77,26 @@
log.info(responseTextEntry);
}
}
- } else if (type == 'error') {
- log.error("Received '" + status + "' error event from " +
identifyElement(source));
+ } else {
+ var status = data.status;
+ log.error("Received '" + type + '@' + status + "'
event from " + identifyElement(source));
log.error("[" + data.responseCode + "] " + data.errorName +
": " + data.errorMessage);
}
} catch (e) {
//ignore logging errors
}
};
+
+ var eventsListener = richfaces.createJSFEventsAdapter({
+ begin: jsfAjaxLogAdapter,
+ beforedomupdate: jsfAjaxLogAdapter,
+ success: jsfAjaxLogAdapter,
+ complete: jsfAjaxLogAdapter,
+ error: jsfAjaxLogAdapter
+ });
- jsf.ajax.addOnEvent(jsfAjaxLogAdapter);
- jsf.ajax.addOnError(jsfAjaxLogAdapter);
+ jsf.ajax.addOnEvent(eventsListener);
+ jsf.ajax.addOnError(eventsListener);
//
}(jQuery, RichFaces, jsf));
Modified:
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces.js/4_0_0.js
===================================================================
---
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces.js/4_0_0.js 2009-08-25
15:54:16 UTC (rev 15296)
+++
root/framework/trunk/impl/src/main/resources/META-INF/resources/richfaces.js/4_0_0.js 2009-08-25
16:34:42 UTC (rev 15297)
@@ -310,19 +310,21 @@
var jsfEventsAdapterEventNames = {
event: {
- 'begin': ['onsubmit'],
- 'success': ['onsuccess', 'oncomplete']
+ 'begin': ['begin'],
+ 'complete': ['beforedomupdate'],
+ 'success': ['success', 'complete']
},
- error: ['onerror', 'oncomplete']
+ error: ['error', 'complete']
};
richfaces.createJSFEventsAdapter = function(handlers) {
//hash of handlers
//supported are:
- // - onsubmit
- // - onsuccess
- // - onerror
- // - oncomplete
+ // - begin
+ // - beforedomupdate
+ // - success
+ // - error
+ // - complete
handlers = handlers || {};
return function(eventData) {
@@ -336,9 +338,17 @@
if (handlerNames) {
for (var i = 0; i < handlerNames.length; i++) {
- var handler = handlers[handlerNames[i]];
+ var eventType = handlerNames[i];
+ var handler = handlers[eventType];
if (handler) {
- handler.call(source, eventData);
+ var event = {};
+ jQuery.extend(event, eventData);
+ event.type = eventType;
+ if (type != 'error') {
+ delete event.status;
+ }
+
+ handler.call(source, event);
}
}
}
@@ -358,6 +368,26 @@
return richfaces.statusName;
}
+ var chain = function() {
+ var functions = arguments;
+ if (functions.length == 1) {
+ return functions[0];
+ } else {
+ return function() {
+ var callResult;
+ for (var i = 0; i < functions.length; i++) {
+ var f = functions[i];
+ callResult = f.apply(this, arguments);
+ }
+
+ return callResult;
+ };
+ }
+ };
+
+ //TODO take events just from .java code using #{...}
+ var AJAX_EVENTS = ['begin', 'complete', 'beforedomupdate'];
+
richfaces.ajax = function(source, event, options) {
options = options || {};
var sourceId = (typeof source == 'object' && source.id) ? source.id :
source;
@@ -369,19 +399,37 @@
if (!parameters.RICHFACES_AJAX) {
parameters.RICHFACES_AJAX = sourceId;
}
+
+ var eventHandlers;
- var eventsHandler;
-
+ for (var i = 0; i < AJAX_EVENTS.length; i++) {
+ var event = AJAX_EVENTS[i];
+ var eventHandlerOption = options[event];
+
+ if (eventHandlerOption) {
+ eventHandlers = eventHandlers || {};
+ eventHandlers[event] = new Function('event', eventHandlerOption);
+ }
+ }
+
if (options.status) {
- eventsHandler = richfaces.createJSFEventsAdapter({
- onsubmit: function() { setGlobalStatusNameVariable(options.status); }
- });
+ var namedStatusEventHandler = function() {
setGlobalStatusNameVariable(options.status); };
+
+ //TODO add support for options.submit
+ eventHandlers = eventHandlers || {};
+ if (eventHandlers.begin) {
+ eventHandlers.begin = chain(namedStatusEventHandler, eventHandlers.begin);
+ } else {
+ eventHandlers.begin = namedStatusEventHandler;
+ }
}
-
+
parameters[sourceId] = sourceId;
- if (eventsHandler) {
- parameters['onevent'] = eventsHandler;
- parameters['onerror'] = eventsHandler;
+
+ if (eventHandlers) {
+ var eventsAdapter = richfaces.createJSFEventsAdapter(eventHandlers);
+ parameters['onevent'] = eventsAdapter;
+ parameters['onerror'] = eventsAdapter;
}
jsf.ajax.request(source, event, parameters);
@@ -439,10 +487,10 @@
thisFunction.initialized = true;
var jsfEventsListener = richfaces.createJSFEventsAdapter({
- onsubmit: function(eventData) { statusAjaxEventHandler(eventData, 'start');
},
- onerror: function(eventData) { statusAjaxEventHandler(eventData, 'error');
},
- onsuccess: function(eventData) { statusAjaxEventHandler(eventData,
'success'); },
- oncomplete: function() { setGlobalStatusNameVariable(null); }
+ begin: function(event) { statusAjaxEventHandler(event, 'start'); },
+ error: function(event) { statusAjaxEventHandler(event, 'error'); },
+ success: function(event) { statusAjaxEventHandler(event, 'success'); },
+ complete: function() { setGlobalStatusNameVariable(null); }
});
jsf.ajax.addOnEvent(jsfEventsListener);
Modified:
root/ui/trunk/components/core/src/main/java/org/richfaces/component/html/HtmlAjaxFunction.java
===================================================================
---
root/ui/trunk/components/core/src/main/java/org/richfaces/component/html/HtmlAjaxFunction.java 2009-08-25
15:54:16 UTC (rev 15296)
+++
root/ui/trunk/components/core/src/main/java/org/richfaces/component/html/HtmlAjaxFunction.java 2009-08-25
16:34:42 UTC (rev 15297)
@@ -1,17 +1,27 @@
package org.richfaces.component.html;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+
import javax.el.ELException;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UICommand;
+import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
-public class HtmlAjaxFunction extends UICommand {
+public class HtmlAjaxFunction extends UICommand implements ClientBehaviorHolder {
public final static String COMPONENT_FAMILY = "javax.faces.Command";
public final static String COMPONENT_TYPE = "org.richfaces.Function";
+ private static final Collection<String> EVENT_NAMES =
Collections.unmodifiableCollection(
+ new LinkedHashSet<String>(Arrays.asList("begin", "complete",
"beforedomupdate"))
+ );
+
public HtmlAjaxFunction() {
setRendererType("org.richfaces.FunctionRenderer");
}
@@ -73,6 +83,8 @@
*/
private String _onbeforedomupdate = null;
+ private String _onbegin = null;
+
/*
* The client-side script method to be called after the request is completed
*/
@@ -553,13 +565,43 @@
this._timeoutSet = true;
}
+ /**
+ * @return the _onbegin
+ */
+ public String getOnbegin() {
+ if (this._onbegin != null) {
+ return this._onbegin;
+ }
+ ValueExpression ve = getValueExpression("onbegin");
+ if (ve != null) {
+ String value = null;
+
+ try {
+ value = (String) ve.getValue(getFacesContext().getELContext());
+ } catch (ELException e) {
+ throw new FacesException(e);
+ }
+
+ return value;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param onbegin the _onbegin to set
+ */
+ public void setOnbegin(String onbegin) {
+ _onbegin = onbegin;
+ }
+
public String getFamily(){
return COMPONENT_FAMILY;
}
@Override
public Object saveState(FacesContext context){
- Object [] state = new Object[23];
+ Object [] state = new Object[24];
state[0] = super.saveState(context);
state[1] = Boolean.valueOf(_ajaxSingle);
state[2] = Boolean.valueOf(_ajaxSingleSet);
@@ -583,6 +625,7 @@
state[20] = _status;
state[21] = Integer.valueOf(_timeout);
state[22] = Boolean.valueOf(_timeoutSet);
+ state[23] = _onbegin;
return state;
}
@@ -612,7 +655,12 @@
_status = (String)states[20];;
_timeout = ((Integer)states[21]).intValue();
_timeoutSet = ((Boolean)states[22]).booleanValue();
+ _onbegin = (String) states[23];
+ }
+ @Override
+ public Collection<String> getEventNames() {
+ return EVENT_NAMES;
}
-
+
}