Created
March 28, 2017 10:17
-
-
Save criedel/315d0cf8dab312870a7bc0d184ef0dd4 to your computer and use it in GitHub Desktop.
FireEvent Tapestry 5.3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import org.apache.commons.lang.ArrayUtils; | |
import org.apache.tapestry5.BindingConstants; | |
import org.apache.tapestry5.ClientElement; | |
import org.apache.tapestry5.ComponentEventCallback; | |
import org.apache.tapestry5.ComponentResources; | |
import org.apache.tapestry5.Link; | |
import org.apache.tapestry5.ValueEncoder; | |
import org.apache.tapestry5.annotations.Environmental; | |
import org.apache.tapestry5.annotations.Import; | |
import org.apache.tapestry5.annotations.InjectContainer; | |
import org.apache.tapestry5.annotations.Parameter; | |
import org.apache.tapestry5.internal.util.Holder; | |
import org.apache.tapestry5.ioc.annotations.Inject; | |
import org.apache.tapestry5.ioc.internal.util.InternalUtils; | |
import org.apache.tapestry5.json.JSONObject; | |
import org.apache.tapestry5.services.Request; | |
import org.apache.tapestry5.services.javascript.JavaScriptSupport; | |
import org.slf4j.Logger; | |
/** | |
* If assigned to any component it can trigger an event (see {@link #eventListener}). The trigger event on the client side can be freely chosen but must be one | |
* of the {@link #supportedClientEvents}. When used with text-fields or select boxes their value will be submitted as event context. This could be used for any | |
* server-side validation. | |
*/ | |
@Import(library = { "fireEvent.js" }) | |
public class FireEvent { | |
public static final String SELECT_COMPONENTID_PARAMETER = "t:selectvalue"; | |
public static final String SELECT_TEXTFIELDID_PARAMETER = "t:textfieldvalue"; | |
public static final String ELEMENTID_PARAMETER = "t:elementId"; | |
/** | |
* The field component to which this mixin is attached. | |
*/ | |
@InjectContainer | |
private ClientElement element; | |
@Inject | |
private ComponentResources componentResources; | |
@Inject | |
private Logger logger; | |
@Inject | |
private Request request; | |
@Environmental | |
private JavaScriptSupport scriptSupport; | |
/** | |
* The client side javascript event that triggers the {@link #eventListener}. Use 'change', 'click', etc. instead of 'onchange' or 'onclick'. | |
*/ | |
@Parameter(defaultPrefix = BindingConstants.LITERAL, required = true, value = "click") | |
private String clientEvent; | |
/** | |
* Name of the event handler method that will be triggered in the component this mixin is applied to. | |
*/ | |
@Parameter(defaultPrefix = BindingConstants.LITERAL, required = true, value = "fire") | |
private String eventListener; | |
@Parameter | |
private int delay; | |
@Parameter | |
private Object[] context; | |
@Parameter(defaultPrefix = BindingConstants.LITERAL, required = false) | |
private String zone; | |
/** | |
* Allows a specific implementation of {@link org.apache.tapestry5.ValueEncoder} to be supplied. This is used to create client-side string values for the | |
* different options. | |
* | |
* @see org.apache.tapestry5.services.ValueEncoderSource | |
*/ | |
@Parameter | |
private ValueEncoder<?> contextEncoder; | |
protected Link createLink(Object[] context) { | |
if (context == null) { | |
context = new Object[1]; | |
} | |
context = ArrayUtils.add(context, eventListener); | |
return componentResources.createEventLink("event", context); | |
} | |
Object onEvent(final Object... context) { | |
for (final Object o : context) { | |
logger.debug("onEvent parameter: {}", o); | |
} | |
for (final String s : request.getParameterNames()) { | |
logger.debug("request param {} = {}", s, request.getParameter(s)); | |
} | |
final List<Object> parameters = new ArrayList<Object>(); | |
for (int i = 0; i < context.length - 1; i++) { | |
if (contextEncoder != null) { | |
parameters.add(toValue((String) context[i])); | |
} else if (context[i] != null) { | |
parameters.add(context[i]); | |
} | |
} | |
// in case the mixin was used on a select component | |
final String selectComponentValue = this.request.getParameter(SELECT_COMPONENTID_PARAMETER); | |
if (selectComponentValue != null) { | |
parameters.add(selectComponentValue); | |
} | |
final String textFieldComponentValue = this.request.getParameter(SELECT_TEXTFIELDID_PARAMETER); | |
if (textFieldComponentValue != null) { | |
parameters.add(textFieldComponentValue); | |
} | |
// add the elemetn Id as last argument to the event context | |
parameters.add(this.request.getParameter(ELEMENTID_PARAMETER)); | |
final Holder<Object> holder = Holder.create(); | |
final ComponentEventCallback<Object> callback = result -> { | |
holder.put(result); | |
return true; | |
}; | |
/* | |
* The last parameter should be the name of the event that we want to trigger. | |
*/ | |
final String eventType = (String) context[context.length - 1]; | |
this.componentResources.triggerEvent(eventType, parameters.toArray(), callback); | |
return holder.get(); | |
} | |
protected Object toValue(final String submittedValue) { | |
return InternalUtils.isBlank(submittedValue) ? null : this.contextEncoder.toValue(submittedValue); | |
} | |
void afterRender() { | |
final Link link = createLink(context); | |
final JSONObject parameter = new JSONObject(); | |
parameter.put("event", this.clientEvent); | |
parameter.put("link", link.toURI()); | |
parameter.put("clientId", this.element.getClientId()); | |
parameter.put("zoneId", this.zone); | |
parameter.put("delay", this.delay); | |
scriptSupport.addInitializerCall("bindEventURL", parameter); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function( $ ) { | |
'use strict'; | |
$.extend(Tapestry.Initializer, { | |
/** | |
* Binds an event handler on an element. Optionally updates a specified zone. | |
* | |
* @param spec.event | |
* event to bind on | |
* @param spec.clientId | |
* the element's id that should listen to the event | |
* @param spec.link | |
* component event request URL | |
* @param spec.zoneId | |
* id of element to update when select is changed | |
*/ | |
bindEventURL : function(spec) { | |
var element = spec.clientId; | |
var event = spec.event; | |
var zoneId = spec.zoneId; | |
var url = spec.link; | |
var el = $('#' + element); | |
var timeoutId; | |
var findZone = function(zoneId) { | |
return zoneId === '^' ? $(el).closest('.t-zone') : $('#' + zoneId); | |
}; | |
var zoneElement = findZone(zoneId); | |
var eventHandler = function(e) { | |
if (!zoneElement || !zoneElement.length) { | |
zoneElement = findZone(zoneId); | |
} | |
var parameters = {}; | |
if (el.is('select')) { | |
var selectValue = $('#' + element + ' :selected').val(); | |
if (selectValue) { | |
parameters['t:selectvalue'] = selectValue; | |
} | |
parameters['event'] = event; | |
} else if (el.is('input')) { | |
var value = $('#' + element).val(); | |
if (value) { | |
parameters['t:textfieldvalue'] = value; | |
} | |
parameters['event'] = event; | |
} | |
zoneElement.tapestryZone('update' , {url : url, params : parameters}); | |
// reset timeout | |
timeoutId = undefined; | |
return false; | |
}; | |
var ignoreKeyCodes = [ 16, 17, 18, 20, 27, 37, 38, 39, 40, 91, 93 ]; | |
el.on(event, {}, function(e) { | |
if (event === 'keyup' && $.inArray(e.keyCode, ignoreKeyCodes) > -1 ) { | |
return false; | |
} | |
if (spec.delay) { | |
window.clearTimeout(timeoutId); | |
timeoutId = window.setTimeout(eventHandler, spec.delay, e); | |
} else { | |
eventHandler(e); | |
} | |
return false; | |
}); | |
} | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment