Replacing LAFutures "Loading" text with internationalized html (and some ranting)

47 views
Skip to first unread message

sebastian....@gmail.com

unread,
Feb 27, 2018, 8:35:46 AM2/27/18
to Lift
Hi
i guess the title says it all :)
i have some LAFuture in a CSS selector like

"#thing" #> LAFuture.build{slowFunction}

Now it shows "Loading" while the future is computing. But how do i change that text?
I want it to be some loading gif and an internationalized text.
So my guess would be somewhere in the _resources?

I already saved the current locale via a SessionVar. So S.?("...") works in comet now.
It is beyond me why this is not the default :/
Does anybody want their comet actors not to be internationalized?
I wasted close to 2 hours finding out how to do that.
It is just a few lines of code but good luck finding any docs explaining the automagic stuff happening there (hint: there aren't any, had to read the source).

And by the way isn't there support for scala futures now?
I have seen something like that in the changelog. Where do i find docs or examples on that?

In general the documentation on basically everything is rather lacking to say the absolute least.

http://cookbook.liftweb.net/ does not exist anymore! But is still linked first on the lift page (this is a way to common trope when it comes to lift related docs)

That "official wiki" assembla  page is 404 heaven and often dated.
Have a look at that: https://app.assembla.com/spaces/liftweb/wiki/Radio_Lists_And_Drop_Downs_From_Enumerations every single link is a 404 and nothing works due to the old bind syntax.
Dropdowns are an absolute essential part of basically every website ever, how can this be messed up?

Simply Lift is from 2011 and way to many pages look like this: https://simply.liftweb.net/index-9.7.html#toc-Section-9.7

I picked Lift as an alternative to rails because fiddling around with routes, doing annoying piping, writing all the js crap by hand, having to deal with awful gems for even the most basic stuff, just seemed like a massive waste of time...

Lifts designer friendly templates are great, comet is great, the community is helpful, so much stuff is just great.
But if i can not even basic shit done in lift without hitting some weird corner cases, i am better off with rails since those guys at least have some sort of documentation
which allows me to fix things quickly without sifting through tons of dispersed, outdated and 404 ridden wikis or random blogs and forums.

It is all too sad to see all the updates coming in and all that work basically goes to waste.
Because none of it is documented in a way where the average Joe User like me can actually make any sense of it.

A rather good example was that CSP debacle where a new feature basically broke basically everything (even the official lift_bootstrap package for download was broken)
and still there is not a single wiki page on how to set up CSP properly.

Using this framework way harder than it should be and for absolutely no good reason.
Sorry for the rant this has become too annoying.

Best regards
Sebastian

Antonio Salazar Cardozo

unread,
Feb 27, 2018, 12:45:37 PM2/27/18
to Lift
Well, there are tens of Rails guys, several directly paid to work on Rails, and only a handful of us,
with none directly paid to work on Lift, so 🤷‍♂️ You can complain about it, or you can act to fix it. If
you'd like to act to fix it, in general your contributions are welcome---both on the documentation
front and on the code front. If you'd prefer to complain about it… I won't stop you, but instead of
being a productive contribution, it's a counterproductive one. It demotivates those of us who do
contribute, without offering any real solutions.

My 2c: if you find yourself needing to announce a rant, consider whether you should edit your
thoughts to bring them from a place of humility, rather than one of entitlement. For example, you
could have rewritten this email to note the issue with CometActor locales and suggest that the
default behavior be changed and offer to open a pull request doing so. There would be two likely
outcomes there: a thankful Lift community, or a note from a committer on backwards compatibility
that needs to be considered, and an ensuing conversation covering it.

Phrased somewhat differently: we know. The knowing is not a solution. Reinforcing the problem
is, in a volunteer project, also not a solution. Offering assistance is. We have an excellent intro
to dependency injection in Lift because Bhashit was kind enough to contribute it, for example.
Much of the wiki content is there for the same reason.
Thanks,
Antonio

Henrik Härkönen

unread,
Feb 27, 2018, 2:57:24 PM2/27/18
to Lift


On Tuesday, 27 February 2018 15:35:46 UTC+2, sebastian....@gmail.com wrote:
Hi
i guess the title says it all :)
i have some LAFuture in a CSS selector like

"#thing" #> LAFuture.build{slowFunction}

Now it shows "Loading" while the future is computing. But how do i change that text?

 
I haven't used LAFutures, but if the mechanism is the same as for LazyLoad snippet (and long ajax calls?), then you are probably facing the issue where the template project
places the animated lazyload gif under /assets/images/ folder but the framwork expecs it to be found from the root (images/lazy-load.gif). You can try to move that images folder right at the root
of the webapp to see if the lazy-load.gif is then loaded. I have a PR open for configuring the path, but it's not there yet.

But if the LAFuture works in some other way, then it might not help.

-Henrik

sebastian....@gmail.com

unread,
Feb 27, 2018, 2:59:57 PM2/27/18
to Lift
Sorry i was angry at some unrelated bug and than this came along.
Usually i try not to bother people like that and i don't want to criticize anybodies work.
But in all honesty the current state is quite anger inducing ;)

I have no idea why non existing stuff is linked directly on the main page.

That dependency injection article is indeed nice but sadly it is hidden away in some obscure doc folder in the git.
Nobody will find it there.

What i wanted to say is that a lot of the docs which do exist are dispersed and you will way too often end up in stuff which looks (or indeed is) plain abandoned.
I am aware that a lot of this is "legacy" and i would offer help in that regard but where do i even begin?

Is the assembla wiki still maintained or even wanted?
Lift Cookbook which i found to be the most useful does not exist anymore...

Maybe there should be some "official" re evaluation on how to get examples and such online.
Because i can not figure out a central spot where to contribute.
Preferably in a central spot ;)

As it currently stands it is impossible to get even dropdowns working by looking at an example linked from the main page :(
How is a newcomer supposed to get anything up and running

sebastian....@gmail.com

unread,
Feb 27, 2018, 3:09:46 PM2/27/18
to Lift
Yup
there is indeed a missing ajax-loader.gif.
Would it be possible to change the whole text to something configurable?
Rendering futures is such a neat feature and having some control over the loading markup would be nice.
Including custom error messages and stuff.
Don't know if that already exists.

Henrik Härkönen

unread,
Feb 27, 2018, 3:35:17 PM2/27/18
to lif...@googlegroups.com
I haven't tried the custom template feature either, but there is one, see from these pages:


also this might help forward with that one:


-Henrik

--
--
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

---
You received this message because you are subscribed to a topic in the Google Groups "Lift" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/liftweb/wnrBPLDRL5E/unsubscribe.
To unsubscribe from this group and all its topics, send an email to liftweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Antonio Salazar Cardozo

unread,
Mar 1, 2018, 9:48:30 AM3/1/18
to Lift
I understand---it induces it in me as well, since I would like it to be better but
don't currently have the bandwidth to make it so.

Regarding nonexisting stuff, please see the first thread this was noted a few days ago.

Lastly, regarding your core issue: Henrik is correct that this is a missing image (you end
up seeing the alt text). Unfortunately, the image and alt text are currently hardcoded and
not internationalized <_<… First things first, we definitely would want to internationalize
the alt text.

If you want more control over the actual content, however, you can do a little bit of extra
work to use the `LazyLoad` snippet, as Henrik suggests. To make it work with a future:

"#id" #> LazyLoad.render(Replace(_, resolveFuture()), S.runTemplate("templates-hidden" :: "loading" :: Nil))

LazyLoad.render takes a (String)=>JsCmd and an optional placeholder template. In
the above example I use `resolveFuture()` as a placeholder for whatever way you need
to resolve your future.

I think you could also set up a CanBind that maps a (NodeSeq, CanResolveAsync) to a
version of the LAFuture bind that uses the NodeSeq as placeholder and replaces it with
the result of the future after it completes; think something like:

  "#id" #> (placeholder, myFuture)

That's pretty gnarly to do right now though. It would be nice to abstract the stuff that's
buried inside the body of asyncResolvableTransform so it can be used by other CanBind
and not-so-CanBind implementations. Almost everything that's there can be abstracted
into a secondary function accessible to any caller. Right now to do the tuple thing you'd
probably need to reproduce most of that method.

Also of note: if we abstracted that body out (and put it, say, on LazyLoadComet or on
LazyLoad or something), you could call it without creating your own CanBind, which seems
like the cleanest and clearest solution.
Thanks,
Antonio

sebastian....@gmail.com

unread,
Mar 2, 2018, 10:55:11 AM3/2/18
to Lift
Thank a lot for the help.
I will have a try at that.

I did not use the LazyLoad because it usually does not work in modals but Futures do (Yay for Futures).
Using a future here was just a convenient way to have the modal pop up and then have its content filled when the data is available.
This stops impatient users from clicking the "load modal" button a ton of times because it just takes a few seconds for a rest request to complete and thus flooding some other api with requests :)

In general being able to use futures in a right hand css bind is quite useful.
When used in conjunction with something like dispatch http and scaffeine future caches it makes for some really neat and clean code.

Best regards
Sebastian

Antonio Salazar Cardozo

unread,
Mar 3, 2018, 8:40:43 AM3/3/18
to Lift
Interesting... how have you seen it fail in modals? In the past this would have been the case because lazy loading uses comets and comets created during an Ajax callback didn’t work so well, but that limitation should no longer exist.

Anyway, I agree that futures are the bomb diggity, just want to make sure we didn’t miss an edge case on the comet-Ajax stuff :)
Thanks,
Antonio

sebastian....@gmail.com

unread,
Mar 6, 2018, 7:26:01 AM3/6/18
to Lift
Maybe this is not in the lift version i am using?
I am on lift 3.1.1

If not i will build an example.

As for the Future loading text:
I copy pasted the implicit you linked to into my snippet and made a few changes:

  implicit def asyncResolvableTransform[ResolvableType, ResolvedType](
   
implicit asyncResolveProvider: CanResolveAsync[ResolvableType, ResolvedType],
             innerTransform
: CanBind[ResolvedType]
 
) = {
   
new CanBind[ResolvableType] {
     
def apply(resolvable:  => ResolvableType)(ns: NodeSeq): Seq[NodeSeq] = {
        val placeholderId
= Helpers.nextFuncName
       
AsyncRenderComet.setupAsync

        val concreteResolvable
: ResolvableType = resolvable

        S
.session.map { session =>
         
// Capture context now.
          val deferredRender
=
            session
.buildDeferredFunction((resolved: ResolvedType) => {
             
AsyncRenderComet.completeAsyncRender(
               
Replace(placeholderId, innerTransform(resolved)(ns).flatten)
             
)
           
})

         
// Actually complete the render once the future is fulfilled.
          asyncResolveProvider
.resolveAsync(concreteResolvable, resolvedResult => deferredRender(resolvedResult))

         
<div id={placeholderId}>
           
// Try to load a ressource
           
<span data-lift="loc?locid=future.loading.text">
             
<img src="/images/ajax-loader.gif" alt="Loading..."/>
           
</span>
          </
div>
       
} openOr {
         
Comment("FIXME: Asynchronous rendering failed for unknown reason.")
       
}
     
}
   
}
 
}

And added the following to _resource:

 <res name="future.loading.text" lang="en" default="true">Loading...</res>
 <res name="future.loading.text" lang="de">Lade...</res>

Since i added the current locale to the session this works the way i wanted :)
I think it should fall back to its default behavior if the ressource is not found.
Maybe this can be made the default?
Not sure if it would break stuff.

Best regard
Sebastian

Antonio Salazar Cardozo

unread,
Mar 6, 2018, 12:44:48 PM3/6/18
to Lift
No, AJAX over comet should have gone out with 3.0.0.

What do you mean about falling back if the resource is not found? Not sure I fully
understand how you envision that working.
Thanks,
Antonio
Reply all
Reply to author
Forward
0 new messages