Lift's JavaScript abstraction layer

166 views
Skip to first unread message

Dmitry Volosnykh

unread,
Apr 22, 2012, 2:04:53 PM4/22/12
to Lift
I am trying to run the following example from "Exploring Lift" book
(with small changes, i.e. I preferred CSS-binding over XML-binding):

object Hello {
import js.{JxMap, Jx, JsCmds, JE}
import JE._
import net.liftweb.http.SHtml._
import net.liftweb.util.BindHelpers._
import JsCmds._

val names = "marius" :: "tyler" :: "derek" :: "dave" :: "jorge" ::
"viktor" :: Nil
def ajaxian =
"#text" #> ajaxText("Type something", {value => {
val matches = names.filter(e => e.indexOf(value) > -1)
SetHtml("items_list", NodeSeq.Empty) &
JsCrVar("items", JsArray(matches.map(Str(_)):_*)) &
JsCrVar("func", Jx(<ul>{
JxMap(JsVar("it"), Jx(<li>{JsVar("it")}</li>))
}</ul>).toJs) &
(ElemById("items_list") ~> JsFunc("appendChild", Call("func",
JsVar("items"))))
}})
}

But I keep getting a list of "JsExp(it)" items when rendered to an
HTML page instead of names in the same-named list. There should be
something wrong with line

JxMap(JsVar("it"), Jx(<li>{JsVar("it")}</li>))

Lift lacks of documentation on JavaScript abstraction layer and
reading corresponding chapters in books and browsing the Lift's
sources do not lead me to an understanding of what's going on. The
only thing I could figure up to now is that Jx creates AnonFunc with
it parameter but I can not convince myself into correct usage of
JsVar("it") in the example provided by Derek in his book.

Dmitry Volosnykh

unread,
Apr 24, 2012, 8:17:22 AM4/24/12
to Lift
Are there any gurus of Lift's Jx/Js classes?
There's no one having answered question on stackoverflow (http://
stackoverflow.com/questions/10270433/lifts-javascript-abstraction-
layer) as well...

On Apr 22, 10:04 pm, Dmitry Volosnykh <dmitry.volosn...@gmail.com>
wrote:

David Pollak

unread,
Apr 24, 2012, 12:38:45 PM4/24/12
to lif...@googlegroups.com
Nagging to get an answer will not make the answer come faster.

In this case, it will make the answer not come from me.

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



--
Visi.Pro, Cloud Computing for the Rest of Us http://visi.pro
Lift, the simply functional web framework http://liftweb.net


Diego Medina

unread,
Apr 24, 2012, 12:48:00 PM4/24/12
to lif...@googlegroups.com
Could you out together a sample
https://www.assembla.com/wiki/show/liftweb/Posting_example_code
application showing the problem?
And would you be k not using all the js abstraction and use some
regular javascript in there?
I personally use a mix on most of my projects.

Regards,

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

Lukasz Kuczera

unread,
Apr 24, 2012, 3:01:40 PM4/24/12
to lif...@googlegroups.com
Agree, JS Abstraction if ok for small js code. Larger js code goes out to js files and is called from within the lift. Your example is as you can tell unreadable. Better to strike balance putting js on client side. It has another benefit you don't send so many bytes by wire.

Richard Dallaway

unread,
Apr 24, 2012, 4:44:39 PM4/24/12
to lif...@googlegroups.com
In case it helps, it looks like a smaller example exhibits the same
symptom. Via http://exploring.liftweb.net/onepage/index.html#lst:Jx-trivial-example

Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server
VM, Java 1.6.0_31).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import net.liftweb.http.js.Jx
import net.liftweb.http.js.Jx

scala> import net.liftweb.http.js.JE.JsVar
import net.liftweb.http.js.JE.JsVar

scala> val x = Jx(<li>{JsVar("it")}</li>)
x: net.liftweb.http.js.Jx = <jx><li>JsExp(it)</li></jx>

scala> x.toJs
res0: net.liftweb.http.js.JsExp =
JsExp(function(it) {var df = document.createDocumentFragment();

var vF183656903091U1DD3G = document.createElement("li");

df.appendChild(vF183656903091U1DD3G);

vF183656903091U1DD3G.appendChild(document.createTextNode("JsExp(it)"));;
return df;})

My understanding of the expectation: that final
document.createTextNode should referencing the Javascript function
parameter "it", not the literal Javascript string of "JsExp(it)".

Richard

Dmitry Volosnykh

unread,
Apr 26, 2012, 4:14:54 AM4/26/12
to Lift
Hi, guys, sorry for delayed response. I'm working hard on my master's
degree at the moment and the project using Lift is just one of the
things I do as a part of it. So, having got stuck with this problem I
decided to concentrate on other things not to spend time irrationally.

As a disclaimer: I am completely new person to web development, so I
am not so good at working with HTML, CSS, JavaScript, AJAX, Comet,
data persistance, session and request management, RESTful services/
APIs, and etc. - that is the plenty of things I somehow managed to
avoid for many years of studying and several years of working, being
engaged in mostly calculational tasks, algorithms, or simple GUI
programming, touching RDBMS's doing nothing more than simple SELECT/
UPDATE requests. That is the reason why I may miss some simple things,
because at some moments I feel my head is going to blow up not being
able to cope with such a massive attack of tough stream of new
information.

Well, first of all, Richard D., I want to thank you so much for
providing extremely minimal example highlighting the issue I faced
with and was unable to provide it myself. I had to be too sleepy or
completely blind in order to comletely miss it. Perhaps, I was in a
hurry and was struggling for trying out more complete example.

Diego M. and Lukasz K., thank for your responses and advices. I am
aware of putting big JS-scripts into a separate file, that is (as it
was stated in the first message of this thread) just an example from
the "Exploring Lift" book. Learning JS abstraction I tried this
example and it didn't work for me, then I spent several hours trying
to work the reason out by myself, reading other books, tutorials,
searching the web and browsing the sources of the Lift - but with no
luck. Only after those attempts I allowed myself to disturb folks of
Lift's Google group.

By the way, Lukasz mentioned that "It has another benefit you don't
send so many bytes by wire." I am not so good at what ends being where
(I mean client and server sides), but I don't understand how a client
can get use of JS in a separate file not having downloaded it a
priori? Or, maybe, you mean that functions generated by Lift do a
remote call to webapp's server?

And finally, David P., you do a great job developing LiftWeb and I
really appreciate it. More over, I feel some excitement learning it
and the Scala language alongside, despite there are (I am from Russia)
only several employees stating in description of their vacancies that
"familiarity with Scala/Lift is a plus". So, mostly I learn them for
self-education.
I admit that sometimes my replies are rude (and most probably you are
much older than me), but I try not to stash my thoughts when I feel
something goes wrong. I have to say that your position on
participating in new-comers' investigations (particularly, of you
framework) is contrary to mine. As for myself, I try to follow simple
rule: if you are able to help newbie, just help him/her, - no need for
lectures and exhortation (maybe I use not the best fitting words, not
being native speaker of English, but you have to get the idea). And,
in the future, if you feel uncomfortable to give an answer/explanation
when I am, as you have said, "nagging", please, just ignore me. Maybe
a month or two ago I was watching some video with you on LiftWeb
framework, and you mentioned that the Lift's community is very
friendly and responsive. It really is, not so much as for it's
originator. Wandering around in the Web while paying interest to Lift,
several times I saw your invitations for live talk in some caffe or
there appear to be some hours at your office when you are ready for
consultations on usage of Lift. Feeling uncomfortable with your
response, I really want to blame you for still being unable to provide
good and thorough documentation (what would be a much greeter
investment in supporting the framework), but I realize that you are,
surely, a busy person, have to take care of your family and writing
Lift at your own will providing it for free, after all. So, it
wouldn't be right. Thanks again for all you do for the world of free
and open source software, just try to be less schoolmarmish.

Dmitry F. Volosnykh
Moscow, Russia

On Apr 25, 12:44 am, Richard Dallaway <rich...@dallaway.com> wrote:
> In case it helps, it looks like a smaller example exhibits the same
> symptom.  Viahttp://exploring.liftweb.net/onepage/index.html#lst:Jx-trivial-example

Naftoli Gugenheim

unread,
Apr 26, 2012, 9:32:45 PM4/26/12
to lif...@googlegroups.com

On Thu, Apr 26, 2012 at 4:14 AM, Dmitry Volosnykh <dmitry.v...@gmail.com> wrote:
By the way, Lukasz mentioned that "It has another benefit you don't
send so many bytes by wire." I am not so good at what ends being where
(I mean client and server sides), but I don't understand how a client
can get use of JS in a separate file not having downloaded it a
priori? Or, maybe, you mean that functions generated by Lift do a
remote call to webapp's server?

I didn't read the whole conversation but I'm guessing the intent is, that static .js files are cached and so don't need to be loaded as much, while javascript written in the dsl, like dynamic snippets, cannot be cached.

Šarūnas

unread,
May 2, 2012, 7:45:53 AM5/2/12
to Lift
Hello,

Sorry if this is not the right place to post a reply but I'm having
the exact same problem with the exact same example. Can anyone give
some suggestions how I could get the parameter "it" instead of string
literal "JsExp(it)" here? It is really confusing.

Thank you in advance,
Šarūnas R.

On Apr 24, 11:44 pm, Richard Dallaway <rich...@dallaway.com> wrote:
> In caseithelps,itlooks like a smaller example exhibits the same
> symptom.  Viahttp://exploring.liftweb.net/onepage/index.html#lst:Jx-trivial-example
> >>>itparameter but I can not convince myself into correct usage of

Naftoli Gugenheim

unread,
May 2, 2012, 6:10:56 PM5/2/12
to lif...@googlegroups.com
You have to write theJsExp.toJsCmd.

Šarūnas

unread,
May 3, 2012, 1:57:39 AM5/3/12
to lif...@googlegroups.com
Hello nafg,
Thank you for your reply!

Do you mean I should write it like this: JsVar("it").toJsCmd ?

Now if I type 'a' and submit it outputs:
  • it
  • it
instead of:
  • JsExp(it)
  • JsExp(it)

I'm clearly still doing something wrong.

Best regards,
Šarūnas R.

On Thursday, May 3, 2012 1:10:56 AM UTC+3, nafg wrote:
You have to write theJsExp.toJsCmd.

Naftoli Gugenheim

unread,
May 3, 2012, 3:46:09 AM5/3/12
to lif...@googlegroups.com
Sorry, maybe I'm not clear what you want. Can you explain from the beginning?

Šarūnas Rimša

unread,
May 3, 2012, 4:06:22 AM5/3/12
to lif...@googlegroups.com
Well, if I understand the example shown here correctly: http://exploring.liftweb.net/master/index-10.html#toc-Section-10.6

By entering 'a' into AjaxText I'm supposed to get two results in div showing "marius" and "dave" while I'm getting "it" and "it" now. As much as I understand JavaScript in LIFT the problem seems to be in here:

Jx(<ul>{JxMap(JsVar("it"), Jx(<li>{JsVar("it").toJsCmd}</li>))}</ul>).toJs (I removed the href tags for simplicity)

While iterating through results "it" should become "marius" and then "dave". It seems that the first attribute of JxMap (being JsVar("it")) is passed correctly as an JavaScript array of two elements (because it shows two results as it supposed to do) but the latter part of the function is not working as I'd want to. It outputs

<li>it</li> and <li>it</li> while I'd want it to output <li>marius</li> and <li>dave</li>

I'm sorry for my English, if I did not made something clear, please let me know and I'll try to rephrase it.

Regards,
Šarūnas R.

Olek Swirski

unread,
May 3, 2012, 6:26:48 PM5/3/12
to lif...@googlegroups.com
Dmitry,

your response to David Pollak was very elaborated, but his point
about nagging still holds. For you it's surely a one time event, but
nagging is quite common and can be annoying for those, who
participate here for a bit longer. If everybody did as you, half of the
content of this mailing list would be "could you answer this one
faster, I'm waiting one day already and still no response!?".
then this forum would deteriorate and would be of less help
for you and all the others. So in order to avoid that, someone
has to be that harsh person, that keeps the order. It's not very
pleasant job, but necessary.

If you read the forum rules, you should know, that bumping the
question is allowed after at least one week of no response.
People here generally do read the messages and if they don't
respond it is because they for some reason can't - either still
solving your problem or just can't devote their time at this very
moment.

I'm happy that people here still helped you, but please
realize it's only because of their kindness and not because
your attitude is accepted. Nagging for an answer is not
welcomed here even if your question is valid. So first behave
yourself and then give the teachings to the elders of this
community.

Dmitry Volosnykh

unread,
May 4, 2012, 8:37:24 AM5/4/12
to Lift
Thanks for thorough explanation. I'll take it into account. Also I
have to submit my apologies if breaking the rules of the community.

Olek Swirski

unread,
May 4, 2012, 9:11:19 AM5/4/12
to lif...@googlegroups.com
Yes Dmitry,
you did break them. The rules were here before, and they stay.
http://groups.google.com/group/liftweb/browse_thread/thread/a145a3e768f36dd7
You can't change them only because your English is not so good,
you're inclined towards sometimes being rude or you don't want
to stash thoughts. The rules are easy enough for everybody.
People here try to stay polite and patient but expect the same
from you. Good that my explanation helped you understand this.

I guess just don't do it again and with time you shell be forgiven :-)

Tyson Hamilton

unread,
Sep 19, 2012, 5:02:44 PM9/19/12
to lif...@googlegroups.com
Well I also ran into this issue while trying to get some street cred on StackOverflow =), which is odd because the code nearly replicates what is on the http://exploring.liftweb.net/master/index-10.html website at chapter 10.6.  I've uploaded some sample code, what should happen is any names that contain the substring typed into the ajax box should be listed.


So typing "j" should yield the name "jorge" in the list, while typing "e" should list "tyler", "derek", "dave", "jorge". I also looked through the JS created and include it below (with shortened function names for readability)





var items = ["tyler", "derek", "dave", "jorge"];

var func = function(it) {
    var df = document.createDocumentFragment();

    var vEBDX = document.createElement("ul");

    df.appendChild(vEBDX);

    var v01FO = it;

    var fAXF4 = function(it) {var df = document.createDocumentFragment();
        var vGK51 = document.createElement("li");

        df.appendChild(vGK51);

        vGK51.appendChild(document.createTextNode("JsExp(it)"));;

        return df;
    };

    for (cANNT = 0; cANNT < v01FO.length; cANNT++) {
        vEBDX.appendChild(fAXF4(v01FO[cANNT]));
    };

    return df;
};
document.getElementById("items_list").appendChild("JsExp(func(items))"); 



Any ways if there is something clearly wrong and it could be pointed out it will help me sleep tonight because I am at a loss.  Thanks,

-Tyson

Olek Swirski

unread,
Sep 19, 2012, 6:25:58 PM9/19/12
to lif...@googlegroups.com
cANNT say what exactly, but definitely something is wrong ...
Maybe try to sleep and look at the code again tomorrow,
from a different perspective
--
Reply all
Reply to author
Forward
0 new messages