You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Nathan Quirynen <na...@pensionarchitects.be> on 2023/02/24 13:11:20 UTC
Preventing double click eventlink and form submit
Hi,
I am looking for a solution to prevent multiple clicks on event links or
form submits in our Tapestry application and in the meanwhile if
possible giving the user visual feedback while the request is being
processed.
We use ajax (async="true") on both our eventlinks and form components,
but there are no javascript events to hook into right before the request
is fired and when the request response is handled. But after some
research I found I can use the zone parameter instead of the async
parameter and then make use of the t5:zone:refresh and
t5:zone:did-update events to do exactly that.
So I came up with following javascript module which can be used for both
form submit buttons and eventlinks:
var init = function(triggerClientId, zoneClientId) {
var trigger = $('#' + triggerClientId);
var zone = $('#' + zoneClientId);
var event_request = 't5:zone:refresh' + '.' +
triggerClientId;
zone.on(event_request, function(e) {
// disable trigger + add css class
trigger.css('pointer-events', 'none');
trigger.addClass('request-in-progress');
var event_response = 't5:zone:did-update' + '.' +
triggerClientId;
zone.on(event_response, function() {
// remove response event handler
zone.off(event_response);
// reenable trigger + remove css class
trigger.css('pointer-events', 'auto');
trigger.removeClass('request-in-progress');
});
});
}
I would make new components AjaxForm/AjaxEventLink to wrap the original
ones and implement everything there.
This seems to work as I hoped it would be, but then a zone element is
added for every EventLink/Form which seems a bit like overkill, but I
don't see another way at the moment.
I was wondering if others have tried to do something like I am, or if
there's any better way of achieving what I am trying here? Or anything
that I am missing could be wrong with my implementation?
Nathan
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Preventing double click eventlink and form submit
Posted by Niran Abeygunawardena <Ni...@Clarivate.com.INVALID>.
Nice solution Ben 😊
We found that we couldn’t visual style a submit input button to give feedback that the request was being processed so instead created a mixin that when the submit button was clicked, it was converted into a link that could then be styled with a spinner and visually disabled. It is a very hacky solution so happy to see alternative solutions especially with a submit input button.
DisableAfterSubmit.java
import org.apache.tapestry5.ClientElement;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.MixinAfter;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
@MixinAfter
public class DisableAfterSubmit
{
@InjectContainer private ClientElement element;
@Environmental private JavaScriptSupport javaScriptSupport;
void afterRender() {
final JSONObject spec = new JSONObject();
spec.put("elementId", element.getClientId());
javaScriptSupport.require("pqc/mixins/DisableAfterSubmit").invoke("initialize").with(spec);
}
}
DisableAfterSubmit.js
(function() {
define(["jquery"], function($j) {
var initialize = function(spec) {
$j('#' + spec.elementId).on('click', spec, afterClick);
};
var afterClick = function(event) {
// AJAX submit hack: to allow a spinner to be positioned by changing from an input[type=submit] to an anchor element
// (as Tapestry form submissions via AJAX do not work now except through an input[type=submit])
var originalElement = $j('#' + event.data.elementId);
var attrs = {'href':'#'};
var valueAttr;
var idAttr = 'hack';
$j.each(originalElement[0].attributes, function(index, attr) {
if (attr.nodeName === 'type') {
// No need to add type=submit so continue
return;
}
if (attr.nodeName === 'value') {
valueAttr = attr.nodeValue;
return;
}
if (attr.nodeName === 'id') {
attrs[attr.nodeName] = attr.nodeValue + idAttr;
return;
}
attrs[attr.nodeName] = attr.nodeValue;
});
originalElement.hide();
originalElement.after(function () {
return $j('<a/>', attrs).append(valueAttr);
});
$j('#' + event.data.elementId + idAttr).addClass('disabled spinner').attr({'role':'alert', 'aria-busy':'true'}).focus();
};
return {
initialize : initialize
};
});
}).call(this);
Cheers,
Niran
PS:
I’m sorry if you receive this email twice as I used different email domain for subscribing to this list and I didn’t see that initial email come through. I have now subscribed using this email address..
From: Ben Weidig <be...@netzgut.net>
Date: Sunday, 26 February 2023 at 14:22
To: Tapestry users <us...@tapestry.apache.org>
Subject: Re: Preventing double click eventlink and form submit
Hi Nathan,
Maybe I misunderstood your goal, but I would solve it with a module
configured by CSS classes or data attributes instead of dedicated
components.
Something along the line of this (untested) CoffeeScript I improvised:
define ['jquery', 't5/core/events'], ($, events) ->
EVENT = 'click.request-in-progress'
register = ->
$('.show-request-in-progress').off(EVENT).on EVENT, ->
$el = $(this)
$el.addClass('request-in-progress')
relatedZone = $el.data('target-zone')
elEvent = "#{t5events.zone.wilUpdate}.##{$el.id}"
zone.on elEvent, ->
zone.off(elEvent)
trigger.removeClass('request-in-progress')
return true
$ ->
register()
$(document).on events.zone.didUpdate, register
See https://urldefense.com/v3/__https://gist.github.com/benweidig/2f2fdb32c74cbd57764b1f7dabbe7079__;!!NknhfzgzgQ!yowXeuZLQZ1AaayarMGyXEXL1HzNLMBuDQXODpgTaFvtxz2t3os3D2bD6FeSb24bEnUMv9tTOwG6dX3IZPu215m5$<https://urldefense.com/v3/__https:/gist.github.com/benweidig/2f2fdb32c74cbd57764b1f7dabbe7079__;!!NknhfzgzgQ!yowXeuZLQZ1AaayarMGyXEXL1HzNLMBuDQXODpgTaFvtxz2t3os3D2bD6FeSb24bEnUMv9tTOwG6dX3IZPu215m5$> for
a nicely formatted version.
This way, you wouldn't need an additional zone and just need to listen to
the content zone to be updated. Only the ".show-request-in-progress" and
"data-target-zone" must be set accordingly.
Actually, the CSS classes isn't needed and the relevant elements could be
targeted via the data attribute.
Cheers
Ben
On Fri, Feb 24, 2023 at 2:11 PM Nathan Quirynen <na...@pensionarchitects.be>
wrote:
> Hi,
>
> I am looking for a solution to prevent multiple clicks on event links or
> form submits in our Tapestry application and in the meanwhile if
> possible giving the user visual feedback while the request is being
> processed.
> We use ajax (async="true") on both our eventlinks and form components,
> but there are no javascript events to hook into right before the request
> is fired and when the request response is handled. But after some
> research I found I can use the zone parameter instead of the async
> parameter and then make use of the t5:zone:refresh and
> t5:zone:did-update events to do exactly that.
> So I came up with following javascript module which can be used for both
> form submit buttons and eventlinks:
>
> var init = function(triggerClientId, zoneClientId) {
>
> var trigger = $('#' + triggerClientId);
> var zone = $('#' + zoneClientId);
>
> var event_request = 't5:zone:refresh' + '.' +
> triggerClientId;
>
> zone.on(event_request, function(e) {
>
> // disable trigger + add css class
> trigger.css('pointer-events', 'none');
> trigger.addClass('request-in-progress');
>
> var event_response = 't5:zone:did-update' + '.' +
> triggerClientId;
> zone.on(event_response, function() {
>
> // remove response event handler
> zone.off(event_response);
>
> // reenable trigger + remove css class
> trigger.css('pointer-events', 'auto');
> trigger.removeClass('request-in-progress');
>
> });
> });
>
> }
>
> I would make new components AjaxForm/AjaxEventLink to wrap the original
> ones and implement everything there.
> This seems to work as I hoped it would be, but then a zone element is
> added for every EventLink/Form which seems a bit like overkill, but I
> don't see another way at the moment.
> I was wondering if others have tried to do something like I am, or if
> there's any better way of achieving what I am trying here? Or anything
> that I am missing could be wrong with my implementation?
>
>
> Nathan
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>
Confidentiality note: This e-mail may contain confidential information from Clarivate. If you are not the intended recipient, be aware that any disclosure, copying, distribution or use of the contents of this e-mail is strictly prohibited. If you have received this e-mail in error, please delete this e-mail and notify the sender immediately.
Re: Preventing double click eventlink and form submit
Posted by Ben Weidig <be...@netzgut.net>.
Hi Nathan,
Maybe I misunderstood your goal, but I would solve it with a module
configured by CSS classes or data attributes instead of dedicated
components.
Something along the line of this (untested) CoffeeScript I improvised:
define ['jquery', 't5/core/events'], ($, events) ->
EVENT = 'click.request-in-progress'
register = ->
$('.show-request-in-progress').off(EVENT).on EVENT, ->
$el = $(this)
$el.addClass('request-in-progress')
relatedZone = $el.data('target-zone')
elEvent = "#{t5events.zone.wilUpdate}.##{$el.id}"
zone.on elEvent, ->
zone.off(elEvent)
trigger.removeClass('request-in-progress')
return true
$ ->
register()
$(document).on events.zone.didUpdate, register
See https://gist.github.com/benweidig/2f2fdb32c74cbd57764b1f7dabbe7079 for
a nicely formatted version.
This way, you wouldn't need an additional zone and just need to listen to
the content zone to be updated. Only the ".show-request-in-progress" and
"data-target-zone" must be set accordingly.
Actually, the CSS classes isn't needed and the relevant elements could be
targeted via the data attribute.
Cheers
Ben
On Fri, Feb 24, 2023 at 2:11 PM Nathan Quirynen <na...@pensionarchitects.be>
wrote:
> Hi,
>
> I am looking for a solution to prevent multiple clicks on event links or
> form submits in our Tapestry application and in the meanwhile if
> possible giving the user visual feedback while the request is being
> processed.
> We use ajax (async="true") on both our eventlinks and form components,
> but there are no javascript events to hook into right before the request
> is fired and when the request response is handled. But after some
> research I found I can use the zone parameter instead of the async
> parameter and then make use of the t5:zone:refresh and
> t5:zone:did-update events to do exactly that.
> So I came up with following javascript module which can be used for both
> form submit buttons and eventlinks:
>
> var init = function(triggerClientId, zoneClientId) {
>
> var trigger = $('#' + triggerClientId);
> var zone = $('#' + zoneClientId);
>
> var event_request = 't5:zone:refresh' + '.' +
> triggerClientId;
>
> zone.on(event_request, function(e) {
>
> // disable trigger + add css class
> trigger.css('pointer-events', 'none');
> trigger.addClass('request-in-progress');
>
> var event_response = 't5:zone:did-update' + '.' +
> triggerClientId;
> zone.on(event_response, function() {
>
> // remove response event handler
> zone.off(event_response);
>
> // reenable trigger + remove css class
> trigger.css('pointer-events', 'auto');
> trigger.removeClass('request-in-progress');
>
> });
> });
>
> }
>
> I would make new components AjaxForm/AjaxEventLink to wrap the original
> ones and implement everything there.
> This seems to work as I hoped it would be, but then a zone element is
> added for every EventLink/Form which seems a bit like overkill, but I
> don't see another way at the moment.
> I was wondering if others have tried to do something like I am, or if
> there's any better way of achieving what I am trying here? Or anything
> that I am missing could be wrong with my implementation?
>
>
> Nathan
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>