Re: ajax onBlur callback with load html: [...]
Johan Brichau <[email protected]> Thu, 16 Sep 2021 10:30:32 +0200
| Newsgroups | gmane.comp.lang.smalltalk.squeak.seaside |
|---|---|
| Message-ID | <[email protected]> |
--===============3450785144630985749==
Content-Type: multipart/alternative;
boundary="Apple-Mail=_6DB5239C-9629-4563-85BA-F305EC658A62"
--Apple-Mail=_6DB5239C-9629-4563-85BA-F305EC658A62
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=utf-8
Hi Bob,
The JQAjax#callback being nil is normal if there is no =E2=80=9Cprimary=E2=
=80=9D callback. This is what you see: the Ajax callback registered on =
the onblur event (using JQAjax>>callback:value:, which is a secondary =
callback) has no primary callback block. The Ajax callback registered on =
the onClick event only has a primary callback block. This is fine and =
works as intended.
The problem you are seeing is on the client side and all about browser =
events: the click on the button triggers the browser=E2=80=99s onBlur =
event first, which triggers the Seaside callback for the blur, which =
triggers another callback to replace the html snippet including the =
button you pressed and the input field that triggered the blur. The html =
load replaces the button you are clicking=E2=80=A6. Now, depending on =
the speed of events and callbacks, the html (including your button) will =
be replaced before or after the browser can send the onClick event to =
the button, which would trigger the Seaside callback for the button.=20
In addition, there is the ordering of events in the browser that makes =
this very complicated to think about: an onClick is only fired after a =
mouseDown and a mouseUp and an onBlur is sent because of the mouseDown =
on the button.
If you include a 100ms delay in the response of the Seaside callback, =
you are effectively making it possible for the browser to trigger the =
onClick event on the original button as well.
Without this delay, the browser will have sent the mouseDown event to =
the button but the button will be replaced before the browser is able to =
trigger a mouseUp and an onClick.=20
Because the new button is not the one you clicked, it will not have =
it=E2=80=99s onclick handler fired.
If you do not replace the button while rendering the Ajax update, it =
works as well.
Doing some console logging can be helpful to debug such issues. See code =
below and try with or without the delay commented out.
html textInput=20
value: self stringValue;=20
onBlur: ((JSStream on: 'console.log(''onblur'')'),
(html jQuery ajax callback: [:value |=20
self stringValue: value. =
(Delay forMilliseconds: 100) wait.
Transcript cr; show: =
Time now displayString , ' value: ' , value asString]
value: (html jQuery this value);=20
onSuccess: ((JSStream on: =
'console.log(''contentload-onblur'')'),(self renderContentLoadDivOn: =
html) ))).
html break; break.=20
html button=20
onClick: ( (JSStream on: 'console.log(''onclick'')'),
(html jQuery ajax callback: [
self stringValue: self =
stringValue , '+'.
Transcript cr; show: Time now =
displayString , ' button: ' , self stringValue asString];
onSuccess: ((JSStream on: =
'console.log(''contentload-onclick'')'),(self renderContentLoadDivOn: =
html) )));
with: 'Press=E2=80=99.
Hope this helps,
Johan
> On 15 Sep 2021, at 23:40, Bob Nemec <[email protected]> wrote:
>=20
>=20
> Wow, this is proving to be challenge. The problem is that in =
JQAjax>>processCallback #callback is sometimes nil. When it is, the =
button press callback is not processed and the button has to be pressed =
again. But, if the onBlur of the text input field has a 100ms delay, the =
#callback value is not nil and the button callback works all the time. =
Which is especially frustrating because adding diagnostic traces slows =
down the first callback enough for things to work.=20
>=20
> This is pushing me to the edge of my Seaside knowledge. I will try =
this same example with the latest Seaside code on Pharo. If it works, =
I'll work on getting us updated (we develop in VW but deploy on GS). If =
not, I'll have a nice packaged problem to raise on the Seaside part of =
the Pharo Discord channel.=20
>=20
> Bob
>=20
> On Tuesday, September 14, 2021, 08:58:31 a.m. EDT, Karsten Kusche =
<[email protected]> wrote:
>=20
>=20
> Hi Bob,
>=20
>> We use onBlur to get the data from input fields and to refresh the =
state of the view. The problem comes up if a button is included in the =
refresh: the ajax callback from that button is not handled (which makes =
sense due to the jQuery load), so the user has to press the button =
again.
>=20
> I=E2=80=99d say it actually doesn=E2=80=99t make any sense. Your =
callbacks are registered, they should work regardless. You could use the =
Web-Browser=E2=80=99s network tool/profiler to see which event-handler =
is fired and what network requests are made. Maybe one of the requests =
doesn=E2=80=99t come through correctly and you can investigate that =
further.=20
>=20
> Some things you should also consider: when you use render =
HTML-Snippets that contain Javascript (like new click-handlers), Seaside =
will automatically add these inside a <script>-tag at the end of this =
snippet and inject that into your DOM at the place where you inject the =
HTML. In your case you should have a <script>-tag at the end of your =
#testDiv.=20
>=20
> I=E2=80=99m not entirely sure about this, but iirc replacing that =
script-tag will also remove all event-handlers that were registered as =
part of this tag. On the other hand replacing the <script> also means =
replacing the <button> so you should still have a working button in any =
case=E2=80=A6 like i said, it doesn=E2=80=99t really make much sense.
>=20
> Karsten
>=20
> _______________________________________________
> seaside mailing list
> [email protected]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
--Apple-Mail=_6DB5239C-9629-4563-85BA-F305EC658A62
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
charset=utf-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; =
charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; =
-webkit-nbsp-mode: space; line-break: after-white-space;" class=3D"">Hi =
Bob,<div class=3D""><br class=3D""></div><div class=3D"">The =
JQAjax#callback being nil is normal if there is no =E2=80=9Cprimary=E2=80=9D=
callback. This is what you see: the Ajax callback registered on the =
onblur event (using JQAjax>>callback:value:, which is a secondary =
callback) has no primary callback block. The Ajax callback registered on =
the onClick event only has a primary callback block. This is fine and =
works as intended.</div><div class=3D""><br class=3D""></div><div =
class=3D"">The problem you are seeing is on the client side and all =
about browser events: the click on the button triggers the browser=E2=80=99=
s onBlur event first, which triggers the Seaside callback for the blur, =
which triggers another callback to replace the html snippet including =
the button you pressed and the input field that triggered the blur. The =
html load replaces the button you are clicking=E2=80=A6. Now, =
depending on the speed of events and callbacks, the html (including your =
button) will be replaced before or after the browser can send the =
onClick event to the button, which would trigger the Seaside callback =
for the button. </div><div class=3D""><br class=3D""></div><div =
class=3D"">In addition, there is the ordering of events in the browser =
that makes this very complicated to think about: an onClick is only =
fired after a mouseDown and a mouseUp and an onBlur is sent because of =
the mouseDown on the button.</div><div class=3D""><br =
class=3D""></div><div class=3D"">If you include a 100ms delay in the =
response of the Seaside callback, you are effectively making it possible =
for the browser to trigger the onClick event on the original button as =
well.</div><div class=3D"">Without this delay, the browser will have =
sent the mouseDown event to the button but the button will be replaced =
before the browser is able to trigger a mouseUp and an =
onClick. </div><div class=3D"">Because the new button is not the =
one you clicked, it will not have it=E2=80=99s onclick handler =
fired.</div><div class=3D""><br class=3D""></div><div class=3D"">If you =
do not replace the button while rendering the Ajax update, it works as =
well.</div><div class=3D""><br class=3D""></div><div class=3D""><div>Doing=
some console logging can be helpful to debug such issues. See code =
below and try with or without the delay commented out.</div><div><br =
class=3D""></div><div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>html =
textInput </div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>value: self =
stringValue; </div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>onBlur: ((JSStream on: =
'console.log(''onblur'')'),</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>(html =
jQuery ajax callback: [:value | </div><div><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>self stringValue: value. (Delay forMilliseconds: =
100) wait.</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> =
</span>Transcript cr; show: Time now displayString , ' value: ' , =
value asString]</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>value: =
(html jQuery this value); </div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>onSuccess: =
((JSStream on: 'console.log(''contentload-onblur'')'),(self =
renderContentLoadDivOn: html) ))).</div><div><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>html =
break; break. </div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>html button </div><div><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>onClick: ( (JSStream on: =
'console.log(''onclick'')'),</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>(html =
jQuery ajax callback: [</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> =
</span>self stringValue: self stringValue , '+'.</div><div><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>Transcript cr; show: Time now displayString , ' button: ' =
, self stringValue asString];</div><div><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>onSuccess: =
((JSStream on: 'console.log(''contentload-onclick'')'),(self =
renderContentLoadDivOn: html) )));</div><div><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>with: 'Press=E2=80=99.</div><div><br class=3D""></div><div><br =
class=3D""></div><div>Hope this helps,</div><div>Johan</div><div><br =
class=3D""></div><blockquote type=3D"cite" class=3D""><div class=3D"">On =
15 Sep 2021, at 23:40, Bob Nemec <<a href=3D"mailto:[email protected]" =
class=3D"">[email protected]</a>> wrote:</div><br =
class=3D"Apple-interchange-newline"><div class=3D""><div =
class=3D"ydpb0c0ebbayahoo-style-wrap" style=3D"caret-color: rgb(0, 0, =
0); font-style: normal; font-variant-caps: normal; font-weight: normal; =
letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; font-family: =
"lucida console", sans-serif; font-size: 13px;"><div dir=3D"ltr"=
data-setdir=3D"false" class=3D""><br =
class=3D"Apple-interchange-newline">Wow, this is proving to be =
challenge. The problem is that in <span =
class=3D"">JQAjax>>processCallback #<span class=3D"">callback is =
sometimes nil. When it is, the button press callback is not processed =
and the button has to be pressed again. But, if the onBlur of the text =
input field has a 100ms delay, the #callback value is not nil and the =
button callback works all the time. Which is especially frustrating =
because adding diagnostic traces slows down the first callback enough =
for things to work. </span></span></div><div dir=3D"ltr" =
data-setdir=3D"false" class=3D""><span class=3D""><span class=3D""><br =
class=3D""></span></span></div><div dir=3D"ltr" data-setdir=3D"false" =
class=3D""><span class=3D""><span class=3D"">This is pushing me to the =
edge of my Seaside knowledge. I will try this same example with the =
latest Seaside code on Pharo. If it works, I'll work on getting us =
updated (we develop in VW but deploy on GS). If not, I'll have a nice =
packaged problem to raise on the Seaside part of the Pharo Discord =
channel. </span></span></div><div dir=3D"ltr" data-setdir=3D"false" =
class=3D""><span class=3D""><span class=3D""><br =
class=3D""></span></span></div><div dir=3D"ltr" data-setdir=3D"false" =
class=3D""><span class=3D""><span class=3D"">Bob</span></span></div><div =
dir=3D"ltr" data-setdir=3D"false" class=3D""><span class=3D""><span =
class=3D""><br class=3D""></span></span></div></div><div =
id=3D"yahoo_quoted_2112089454" class=3D"yahoo_quoted" =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;"><div =
style=3D"font-family: "Helvetica Neue", Helvetica, Arial, =
sans-serif; font-size: 13px; color: rgb(38, 40, 42);" class=3D""><div =
class=3D"">On Tuesday, September 14, 2021, 08:58:31 a.m. EDT, Karsten =
Kusche <<a href=3D"mailto:[email protected]" =
class=3D"">[email protected]</a>> wrote:</div><div class=3D""><br =
class=3D""></div><div class=3D""><br class=3D""></div><div class=3D""><div=
id=3D"yiv0857676699" class=3D""><div class=3D""><div =
style=3D"font-family: Helvetica, Arial; font-size: 13px;" class=3D"">Hi =
Bob,</div><div class=3D"yiv0857676699yqt6264543426" =
id=3D"yiv0857676699yqtfd02179"><div style=3D"font-family: Helvetica, =
Arial; font-size: 13px;" class=3D""><br clear=3D"none" =
class=3D""></div></div><div class=3D""><div =
class=3D"yiv0857676699yqt6264543426" =
id=3D"yiv0857676699yqtfd06452"></div><blockquote =
class=3D"yiv0857676699clean_bq" type=3D"cite" style=3D"font-family: =
Helvetica, Arial; font-size: 13px; font-style: normal; font-weight: =
normal; letter-spacing: normal; text-indent: 0px; text-transform: none; =
white-space: normal; word-spacing: 0px; text-decoration: none;"><div =
class=3D"yiv0857676699yqt6264543426" id=3D"yiv0857676699yqtfd95783"><span =
class=3D""></span><div class=3D"">We use onBlur to get the data from =
input fields and to refresh the state of the view. The problem comes up =
if a button is included in the refresh: the ajax callback from that =
button is not handled (which makes sense due to the jQuery load), so the =
user has to press the button again.</div></div></blockquote></div><p =
class=3D"">I=E2=80=99d say it actually doesn=E2=80=99t make any sense. =
Your callbacks are registered, they should work regardless. You could =
use the Web-Browser=E2=80=99s network tool/profiler to see which =
event-handler is fired and what network requests are made. Maybe one of =
the requests doesn=E2=80=99t come through correctly and you can =
investigate that further. </p><p class=3D"">Some things you should =
also consider: when you use render HTML-Snippets that contain Javascript =
(like new click-handlers), Seaside will automatically add these inside a =
<script>-tag at the end of this snippet and inject that into your =
DOM at the place where you inject the HTML. In your case you should have =
a <script>-tag at the end of your #testDiv. </p><p =
class=3D"">I=E2=80=99m not entirely sure about this, but iirc replacing =
that script-tag will also remove all event-handlers that were registered =
as part of this tag. On the other hand replacing the <script> also =
means replacing the <button> so you should still have a working =
button in any case=E2=80=A6 like i said, it doesn=E2=80=99t really make =
much sense.</p><p class=3D"">Karsten</p><div =
class=3D"yiv0857676699yqt6264543426" id=3D"yiv0857676699yqtfd17937"><div =
class=3D""></div></div></div></div></div></div></div><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;" =
class=3D"">_______________________________________________</span><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;" class=3D""><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;" class=3D"">seaside mailing list</span><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;" class=3D""><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;" class=3D""><a =
href=3D"mailto:[email protected]" =
class=3D"">[email protected]</a></span><br =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none;" class=3D""><span =
style=3D"caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: =
12px; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; text-align: start; text-indent: 0px; =
text-transform: none; white-space: normal; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; text-decoration: none; float: none; =
display: inline !important;" class=3D""><a =
href=3D"http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside=
" =
class=3D"">http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seas=
ide</a></span></div></blockquote></div><br class=3D""></div></body></html>=
--Apple-Mail=_6DB5239C-9629-4563-85BA-F305EC658A62--
--===============3450785144630985749==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kc2Vhc2lkZSBt
YWlsaW5nIGxpc3QKc2Vhc2lkZUBsaXN0cy5zcXVlYWtmb3VuZGF0aW9uLm9yZwpodHRwOi8vbGlz
dHMuc3F1ZWFrZm91bmRhdGlvbi5vcmcvY2dpLWJpbi9tYWlsbWFuL2xpc3RpbmZvL3NlYXNpZGUK
--===============3450785144630985749==--