This should be easy... right?

64 views
Skip to first unread message

Jake

unread,
Mar 23, 2010, 5:11:22 PM3/23/10
to Lift
Hi all,

I recently finished the Getting Started document and everything
clicked... well, mostly at least.

One of the things that bugged me was the behavior of the TD.desc
swappable when switching between static description span and text
input. It's possible out of the box to set multiple fields editable
and have them all switch back when one of them blurs. While this
doesn't seem to allow any other goofy behavior, it's goofy enough on
its own.

I've spent a bit of time trying to figure out the most graceful way of
forcing focus on the field after it's been swapped to "input field"
mode, but it's obviously not as simple as injecting FocusOnLoad
somewhere in the TD class.

Could one of you please enlighten me as to a relatively simple way to
go about this (if it is indeed relatively simple to fix?)

Thanks!
Jake

Lukasz Kuczera

unread,
Mar 24, 2010, 7:09:35 AM3/24/10
to Lift
You can call some js function that will focus after submit.

Jake

unread,
Mar 24, 2010, 9:57:47 AM3/24/10
to Lift
Actually, after doing a bit more digging, this is the code on the
static text span:

onclick="jQuery('#'+'F1106112131740EGU').hide();
jQuery('#'+'F1106112131741RCN').show().each(function(i) {var t = this;
setTimeout(function() { t.focus(); }, 200);}); return false;;"

F1106112131741RCN is the generated id of the text input, so by this
code it should be setting the focus automatically anyway. However, it
doesn't work in any browser I've tested (IE8, FFX 3.6, Chrome.)

Why isn't the:

function(i) {var t = this; setTimeout(function() { t.focus(); },
200);}

...portion being supplied as a callback to jQuery.show() instead of
being chained in? It would remove the need to setTimeout by 200ms and
you could just have it set focus after showing.

a la:

jQuery('#'+'F1106112131741RCN').show(function() { t.focus(); })

Is there some other internal reason I'm missing? :-)

Thanks!
Jake

Jake Vose

unread,
Mar 24, 2010, 2:46:07 PM3/24/10
to Lift
The line of code I referenced as being a better behavior isn't 100%
correct, sorry -- I was on my way to a meeting. :-)

Lukasz Kuczera

unread,
Mar 24, 2010, 5:19:28 PM3/24/10
to Lift
Please show your code and explain what you want to achieve.

Listing 15: desc method in TD class
private def desc(td: ToDo, reDraw: () => JsCmd) =
swappable(<span>{td.desc}</span>,
<span>{ajaxText(td.desc,
v => {td.desc(v).save; reDraw()})}
</span>)

It calls reDraw. You can stick together Js functions on Lift side see
http://scala-tools.org/mvnsites-snapshots/liftweb/lift-base/lift-webkit/scaladocs/net/liftweb/http/js/JsCmd.html

Method "&" takes JsCmd and returns JsCmd so you can pass reDraw as
something like:

reDraw & Focus("your id you want to focus on")

This last statement is function of type JsCmd. I hope this helps.

Jake Vose

unread,
Mar 24, 2010, 6:24:36 PM3/24/10
to Lift
Hi Lukasz,

This is exactly the code I'm using (unchanged) -- the results of the
Getting Started tutorial.

Thank you for your response, I'm sure that will come in handy! How
exactly would I reference a component by ID, though? Say, for
instance, if I had used ajaxText to generate myself a component?

...meanwhile...

To rephrase my last posts a bit, the default swappable appears that it
SHOULD be doing what I want it to... but isn't. I believe that I may
have uncovered an issue with the core functionality in what's
generated by swappable.

As I posted above, the JS generated by the default swappable shows
that when the (static) span is clicked, the following steps are
enacted:

1. the static span is hidden
2. the input box is shown
3. an interval is set which causes focus on the input box after 200ms

What I'm seeing is that this does not actually work in any browser. I
am additionally wondering why this is being done by setting an
interval as timer-driven events seem inferior to the ability to
provide a callback and can lead to timing issues in larger
applications.

Thanks!
Jake


On Mar 24, 5:19 pm, Lukasz Kuczera <kuk...@gmail.com> wrote:
> Please show your code and explain what you want to achieve.
>
> Listing 15:     desc method in TD class
> private def desc(td: ToDo, reDraw: () => JsCmd) =
>  swappable(<span>{td.desc}</span>,
>          <span>{ajaxText(td.desc,
>                      v => {td.desc(v).save; reDraw()})}
>          </span>)
>

> It calls reDraw. You can stick together Js functions on Lift side seehttp://scala-tools.org/mvnsites-snapshots/liftweb/lift-base/lift-webk...

Jake Vose

unread,
Mar 25, 2010, 8:48:47 AM3/25/10
to Lift
Ok - this is starting to make more sense now. :-)

I took a look at the swappable implementation on GitHub, which
included the following:

(from framework\lift-base\lift-webkit\src\main\resources\toserve
\jlift.js in master):

visible.onclick = function() {
jQuery(visible).hide();
jQuery(hidden).show();
jQuery(hidden).focus();
jQuery(hidden).children(":input").focus();
return false;
};

This code would not have been responsible for generating the jQuery I
was seeing on my ajaxText's onclick:

onclick="jQuery('#'+'F1106112131740EGU').hide();
jQuery('#'+'F1106112131741RCN').show().each(function(i) {var t = this;
setTimeout(function() { t.focus(); }, 200);}); return false;;"

This leads me to believe that it's already been changed/fixed since
the version that I grabbed when I created my project using the Getting
Started instructions:

mvn archetype:generate -U \
-DarchetypeGroupId=net.liftweb \
-DarchetypeArtifactId=lift-archetype-basic \
-DarchetypeVersion=1.0 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=com.liftworkshop \
-DartifactId=todo \
-Dversion=0.1-SNAPSHOT

Finding an already-fixed bug is a good thing! :-)

So on my end, I next need to learn more about Git, Maven, and the
build process so that I can pull a later rev.

For purposes of the Getting Started guide, this may need to be updated
as the rev used _does_ contain this bug.

Jake

Lukasz Kuczera

unread,
Mar 25, 2010, 4:02:36 PM3/25/10
to Lift
Shouldn't guide be updated to 2.0 ish ?

Jake Vose

unread,
Mar 30, 2010, 2:59:15 PM3/30/10
to Lift
Ok, so I've gone back to the books and spent some more time digging.
jlift.js has not been modified since 2008, but it is an actual bug:

(from the swappable implementation in framework\lift-base\lift-webkit
\src\main\resources\toserve\jlift.js):

visible.onclick = function() {
jQuery(visible).hide();
jQuery(hidden).show();
jQuery(hidden).focus();

jQuery(hidden).children(":input").focus();
return false;
};

This line:


jQuery(hidden).children(":input").focus();

...will never evaluate to any child objects. ":input" is not a valid
selector.

What is the intent? To allow only the top-level tag and its direct
descendants to be focused on?

One solution may be:

visible.onclick = function() {
jQuery(visible).hide();
jQuery(hidden).show();

if (jQuery(hidden).is("input"))
jQuery(hidden).focus();
else


jQuery(hidden).children("input").focus();
return false;
};

Currently, due to the code in the Getting Started guide, it is the
surrounding span of the hidden input which gains focus when the static
text is clicked. I've been trying to work around it without
success...

Jake

Marius

unread,
Mar 31, 2010, 2:33:40 AM3/31/10
to Lift
Jake, please open a ticket describing the current behavior and the
expected one.

Br's,
Marius

Jake Vose

unread,
Mar 31, 2010, 11:16:30 AM3/31/10
to Lift
Thanks, Marius. Created ticket #449: http://www.assembla.com/spaces/liftweb/tickets/449
and assigned to you (no milestone set, though.) It's not a production
issue by any means, just something I stumbled on.

Jake

Dan Gravell

unread,
Dec 6, 2012, 5:41:56 AM12/6/12
to lif...@googlegroups.com
I've been struggling with SHtml.swappable containing a span (default element shown) and an AutoComplete (the hidden element). Using the SHtml.swappable does not give the AutoComplete's input the focus.

So I found this old bug which was apparently fixed, but it doesn't look like that in the source. If I simply use this code in my own project, it works as expected.

Does anyone know why/whether this fix was undone?

Dan

Dan Gravell

unread,
Dec 6, 2012, 7:23:14 AM12/6/12
to lif...@googlegroups.com
And also I had to attach the 'focusout' JQ event to the hidden span, so that lost focus for child objects also meant the swap worked in swapping back to the original label...

My code now looks like...

  def inputFocusSwappable(shown: Elem, hidden: Elem): Elem = {

def showAndFocus(id: String) = JqId(id) ~> new JsMember {
def toJsCmd = "show(); if (jQuery(hidden).is('input')) jQuery(" + id + ").focus(); else jQuery(" + id + ").find('input')[0].focus()"
}
  
    val (rs, sid) = findOrAddId(shown)
    val (rh, hid) = findOrAddId(hidden)
    val ui = LiftRules.jsArtifacts
    (<span>
        {rs % ("onclick" -> (ui.hide(sid).cmd & showAndFocus(hid).cmd & JsRaw("return false;")))}
    {rh % ("style" -> "display: none")}
    {Script(Jq("#" + hid) ~> JsFunc("focusout", AnonFunc((ui.show(sid).cmd & ui.hide(hid).cmd))) )}
     </span>)
  }

Diego Medina

unread,
Dec 18, 2012, 11:52:05 PM12/18/12
to Lift
If you put together a sample app [1] showing the issue, I may be able to help

[1] https://www.assembla.com/wiki/show/liftweb/Posting_example_code

Thanks

Diego
> --
> --
> Lift, the simply functional web framework: http://liftweb.net
> Code: http://github.com/lift
> Discussion: http://groups.google.com/group/liftweb
> Stuck? Help us help you:
> https://www.assembla.com/wiki/show/liftweb/Posting_example_code
>
>
>



--
Diego Medina
Lift/Scala Developer
di...@fmpwizard.com
http://www.fmpwizard.com
Reply all
Reply to author
Forward
0 new messages