On Thu, Nov 19, 2009 at 1:10 AM, Thiago H. de Paula Figueiredo < thiag...@gmail.com> wrote:
> Em Wed, 18 Nov 2009 20:00:22 -0200, Ilya Obshadko <ilya.obsha...@gmail.com> > escreveu: > > > Finally, I've managed to create generic-purpose mixin that can trigger >> form submit on any type of event and on any element within t:form component. >> It works using standard Tapestry mechanisms (similarly to original Submit >> component), supports multiple submit triggers within single form >> (analogous to multiple submit buttons). >> > > Please post it here. :) > > Okay. Mixin source: @IncludeJavaScriptLibrary("submitonevent.js") public class SubmitOnEvent { @Environmental private RenderSupport renderSupport; @Environmental private FormSupport formSupport; @InjectContainer private ClientElement container; @Inject private ComponentResources resources; @Inject private Request request; /** * Component event that triggers form submission; must be the name of REAL JavaScript * event (click, change, blur etc.) */ @Parameter(required=true,allowNull=false,defaultPrefix="literal") private String monitorEvent; /** * Tapestry submit event name that will be simulated during form submission */ @Parameter(required=true,allowNull=false,defaultPrefix="literal") private String submitEvent; /** * ID of the field that MUST have a value before form submission. * If field is empty, event is not triggered. */ @Parameter(required=false,allowNull=false,defaultPrefix="literal") private String requiredField; /** * Form submit context */ @Parameter(required=false,allowNull=false,defaultPrefix="prop") private Object[] submitContext; private static class ProcessFakeSubmission implementsComponentAction<SubmitOnEvent> { private static final long serialVersionUID = -2205200857980521346L; private String fakeSubmitName; public ProcessFakeSubmission ( String fakeSubmitName ) { this.fakeSubmitName = fakeSubmitName; } public void execute ( SubmitOnEvent component ) { component.processFakeSubmission ( fakeSubmitName ); } } public void afterRender () { final String formId = formSupport.getClientId (); formSupport.store ( this, new ProcessFakeSubmission ( "submit_" + container.getClientId () ) ); renderSupport.addInit ( "submitOnChange", new JSONArray ( monitorEvent, formId, container.getClientId (), requiredField ) ); } private void processFakeSubmission ( String elementName ) { String value = request.getParameter ( elementName ); if ( value == null ) return; Runnable sendNotification = new Runnable () { public void run () { resources.triggerEvent ( submitEvent, submitContext, null ); } }; formSupport.defer ( sendNotification ); } } and JavaScript: Tapestry.Initializer.submitOnChange = function(eventName, formId, elementId, requiredField) { $(elementId).observe (eventName, function(event) { if ( ( requiredField && $(requiredField).value ) || ! requiredField ) { var hiddenSubmit = document.createElement("input"); hiddenSubmit.type = "submit"; hiddenSubmit.name = "submit_" + elementId; hiddenSubmit.style.visibility = "hidden"; hiddenSubmit.style.display = "none"; $(formId).appendChild(hiddenSubmit); hiddenSubmit.click(); } }); }; The idea behind 'requiredField' parameter is simple: if parameter is specified, this field must be filled in before triggering submit event. Probably it's better to leave that up to Tapestry built-in client-side validation, but I don't use it in my project (it's very intrusive and its visual features doesn't fit the website design). Enjoy! -- Ilya Obshadko