Multi-web server ajax callback with refresh on Enter

169 Views Asked by At

Question about how to send a jQuery callback with an onSuccess: refresh from a textInput when the user presses [Enter]. We use the [Enter] press to trigger a search callback.

Our GS Seaside app uses HAProxy. This means the onSuccess: script is handled by a different gem than the one that handles the callback. Because of this, users will sometimes get the refresh because the callback, which to them looks like a lost input (a browser F5 refresh shows the right state). If running single gem or in a VW / Pharo image this problem does not come up.

I can work around the problem by using...

async: false;

...but that prevents me from show any kind of waiting feedback (I normally use a busy gif).

So, the question is: in a multi-web server configuration, how can you code a callback to...

1 - show a busy gif

2 - trigger the search callback

3 - refresh the display when done

...all in that order.

Using a form submission callback is a problem because multiple text inputs can trigger the search, since the callback is 'set value + do search', by virtual of the default [Enter] press.

For the JS callback, I'm using...

    self onKeyPress: (
    (JSStream 
        on: '(window.event ? window.event.keyCode : event.which) == 13')
        then: (canvas jQuery ajax callback: aBlock value: canvas jQuery this value))

It all works fine, except for the missing busy gif, due to the 'async: false'. Any suggestions?

3

There are 3 best solutions below

0
On BEST ANSWER

Fix ended up being trivial: needed to include 'event.preventDefault();' in the [Enter] key script. Seems obvious in hindsight.

if ((window.event ? window.event.keyCode : event.which) == 13) {
            event.preventDefault();
        };'
2
On

This problem is confirmed to be a narrow configuration symptom: GemStone with multiple gems. On every other configuration Seaside / javascript behaves as expected. I will follow this up as a vendor problem. Thanks to everyone that looked at it (this was also posted on other forums).

8
On

You can define a beforeSend and a complete handler to show and hide the loading indicator while the request is being processed. The global parameter set to false is meant to ignore your existing handlers to process request start and end (the mentioned spinner), and only use these defined in the particular instance of the JQAjax object.


    ((html jQuery ajax)
        async: false;
        global: false; "https://api.jquery.com/category/ajax/global-ajax-event-handlers/"
        callback: aBlock value: canvas jQuery this value;
        onBeforeSend: (html jQuery id: 'indicator') show;
        onSuccess: ((html jQuery id: 'fieldId') load html: [:h | ]);
        onComplete: (html jQuery id: 'indicator') hide;

That said, keep in mind that doing a synchronous AJAX call is discouraged since it will block the whole UI thread until the request is resolved.

So it's not completely clear how you manage the state in different worker images (gems, in this case) returning different things (probably because of having different sessions), so it's also not clear to me why doing an async XHR request will be served differently to doing it synchronously, I never experienced that.

From the small sample you mention, it can't be deduced what is the "refresh" part of your code. So maybe, providing more context will help us give you more accurate answers.