Menu widget

29 views
Skip to first unread message

Marius

unread,
Mar 21, 2009, 5:44:06 AM3/21/09
to Lift
Folks,

I just committed the menu widget. Now the Widgets test site uses this
widget instead of the traditional builtin menu. You can also specify
the style of the menu using MenuStyle.HORIZONTAL, MenuStyle.VERTICAL
and MenuStyle.NAVBAR.

All these thanks to superfish jquery plugin http://users.tpg.com.au/j_birch/plugins/superfish/

Oh you can also customize the superfish plugin by specifying the JsObj
to set the properties.

Thoughts/suggestions ?

Br's,
Marius

TylerWeir

unread,
Mar 21, 2009, 9:19:18 AM3/21/09
to Lift
You are unstoppable Marius! Excellent!

On Mar 21, 5:44 am, Marius <marius.dan...@gmail.com> wrote:
> Folks,
>
> I just committed the menu widget. Now the Widgets test site uses this
> widget instead of the traditional builtin menu. You can also specify
> the style of the menu using MenuStyle.HORIZONTAL,  MenuStyle.VERTICAL
> and  MenuStyle.NAVBAR.
>
> All these thanks to superfish jquery pluginhttp://users.tpg.com.au/j_birch/plugins/superfish/

Derek Chen-Becker

unread,
Mar 21, 2009, 9:51:36 AM3/21/09
to lif...@googlegroups.com
Awesome! It looks like you did end up having to essentially duplicate the code in the builtin Menu.builder snippet method to get this working. When I was looking at it I thought that it might be nice to have a general way of making the builtin Menu snippet just render the whole tree in case anyone else wants to use it (for a site navigation page, etc). I was thinking that we could add an optional parameter that would essentially do that, then you could just have the snippet look like:

<lift:Menu.builder expandAll="true" />

Or something. I suppose it's a pretty small chunk of code, but if someone else wants to do something similar it means they have to copy it all over.

Thoughts?

Derek

marius d.

unread,
Mar 21, 2009, 10:22:46 AM3/21/09
to Lift
Similar approach yes, duplicate not quite. It just utilizes that the
API provided by SiteMap, MenuItem etc. and walks through a tree
structure and build <ul>/<li> constructs.

We could make the SiteMap to be self aware of rendering itself to <ul>/
<li> constructs but personally I don't really see this as being
necessary. Nonetheless if there are compelling reasons to do so I'd
like to know them. ... I like things do be decoupled and SIteMap is
expressive enough to represent it in so many ways,

Br's,
Marius

On Mar 21, 3:51 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> Awesome! It looks like you did end up having to essentially duplicate the
> code in the builtin Menu.builder snippet method to get this working. When I
> was looking at it I thought that it might be nice to have a general way of
> making the builtin Menu snippet just render the whole tree in case anyone
> else wants to use it (for a site navigation page, etc). I was thinking that
> we could add an optional parameter that would essentially do that, then you
> could just have the snippet look like:
>
> <lift:Menu.builder expandAll="true" />
>
> Or something. I suppose it's a pretty small chunk of code, but if someone
> else wants to do something similar it means they have to copy it all over.
>
> Thoughts?
>
> Derek
>

Derek Chen-Becker

unread,
Mar 21, 2009, 11:41:14 AM3/21/09
to lif...@googlegroups.com
Sorry, what I mean is that the builtin Menu snippet code is duplicated, not SiteMap. For instance, here's how the builtin snippet generates the ULs:

    S.request.map(_.buildMenu.lines.toList match {
        case Nil => List(Text("No Navigation Defined."))
        case xs =>
          val liMap = S.prefixedAttrsToMap("li")
          val li = S.mapToAttrs(liMap)

          def buildANavItem(i: MenuItem) = {
            i match {
              case MenuItem(text, uri, kids, true, _, _) =>
                (<li><span>{text}</span>{buildUlLine(kids)}</li>) % S.prefixedAttrsToMetaData("li_item", liMap)
              case MenuItem(text, uri, kids,  _, true, _) =>
                (<li><a href={uri}>{text}</a>{buildUlLine(kids)}</li>) % S.prefixedAttrsToMetaData("li_path", liMap)
              case MenuItem(text, uri, kids, _, _, _) =>
                (<li><a href={uri}>{text}</a>{buildUlLine(kids)}</li> % li)
            }
          }

          def buildUlLine(in: Seq[MenuItem]): Node = if (in.isEmpty) Text("")
          else <ul>{in.flatMap(buildANavItem)}</ul> %
          S.prefixedAttrsToMetaData("ul")

          buildUlLine(xs)

      })

And here's the new code you put together:

  private def buildMenu(kids: Seq[MenuItem]): Elem = {
    <ul>{
      for (m <- kids) yield {
        <li>{
          <a href={m.uri}>{m.text}</a> ++ (m.kids.isEmpty match {
            case true => NodeSeq.Empty
            case _ => buildMenu(m.kids)
          })
        }</li>
      }
    }</ul>
  }

What you've written is very similar, albeit without some of the attribute handling, etc. I was just saying that if someone else comes along and finds a need for fully expanding SiteMap into nested ULs, then they have to write similar code again. It's a fairly small snippet of code, but I don't know that that's really an argument against providing it as a general mechanism. I mean, chooseTemplate is just a few lines, but we include it because it's useful. I would be happy to make changes to the builtin Menu snippet on a new branch to show what I mean if you'd like.

Derek

marius d.

unread,
Mar 21, 2009, 12:01:25 PM3/21/09
to Lift
I think I am aware what you meant ... If you want to make SiteMap to
know how to render itself as <ul>/<li> hence "centralize" this fine by
me. I have nothing against it, I just don't see the need ... the good
news is that it may be just me ;)

The analogy with chooseTemplate is not very relevant IMHO because
choseeTemplate is a construct that one can use in many application
context whereas SiteMap is typically only one. But by all means don't
let me stay in your way:)

If you are implementing this in SIteMap then perhaps you should make
both Menu built in snippet and MenuWidget to use it?

Br's,
Marius

Derek Chen-Becker

unread,
Mar 21, 2009, 12:22:30 PM3/21/09
to lif...@googlegroups.com
I think I'm not being very clear. I'm going to modify the builtin Menu snippet, not SiteMap. In my view, SiteMap should not be concerned with how it's rendered, but the builtin snippet surely should be able to handle this. Once I have the Menu snippet modified, the MenuWidget class would just embed a <lift:Menu.builder expandAll="true" /> tag where it wants the menu. I'll work on it this weekend and let you know when I have something usable.

Derek

James Matlik

unread,
Mar 21, 2009, 12:29:20 PM3/21/09
to lif...@googlegroups.com
Is there a running version of the widgets site online, or is this only available in source format?  It would be nice to have something like this linked to the liftweb home page or wiki for people to test drive these features at zero cost.  I did a quick look there and didn't find anything of the kind.

marius d.

unread,
Mar 21, 2009, 12:56:09 PM3/21/09
to Lift
Not sure what to say about having the MenuWidget depending on the
builtin Menu snippet. But go ahead ...

On Mar 21, 6:22 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> I think I'm not being very clear. I'm going to modify the builtin Menu
> snippet, not SiteMap. In my view, SiteMap should not be concerned with how
> it's rendered, but the builtin snippet surely should be able to handle this.
> Once I have the Menu snippet modified, the MenuWidget class would just embed
> a <lift:Menu.builder expandAll="true" /> tag where it wants the menu. I'll
> work on it this weekend and let you know when I have something usable.
>
> Derek
>

marius d.

unread,
Mar 21, 2009, 12:57:11 PM3/21/09
to Lift
Good point ... perhaps put it on the Lift online demo application?

Br's,
Marius

On Mar 21, 6:29 pm, James Matlik <james.mat...@gmail.com> wrote:
> Is there a running version of the widgets site online, or is this only
> available in source format?  It would be nice to have something like this
> linked to the liftweb home page or wiki for people to test drive these
> features at zero cost.  I did a quick look there and didn't find anything of
> the kind.
>

Charles F. Munat

unread,
Mar 21, 2009, 5:04:28 PM3/21/09
to lif...@googlegroups.com
+1

I am understanding exactly what you have in mind and think it's a great
idea. I wrote some kludgy code months ago (I knew zero about Scala back
then -- now I know *infinity* times more! :-) to do pretty much the same
thing, and I ended up completely rewriting the Menu snippet to my own
needs. More flexibility == good, I think.

Chas.

(For anyone a little slow on the uptake this fine Saturday, please note
that anything times zero is still zero.)

Derek Chen-Becker wrote:
> I think I'm not being very clear. I'm going to modify the builtin Menu
> snippet, not SiteMap. In my view, SiteMap should not be concerned with
> how it's rendered, but the builtin snippet surely should be able to
> handle this. Once I have the Menu snippet modified, the MenuWidget class
> would just embed a <lift:Menu.builder expandAll="true" /> tag where it
> wants the menu. I'll work on it this weekend and let you know when I
> have something usable.
>
> Derek
>
> On Sat, Mar 21, 2009 at 10:01 AM, marius d. <marius...@gmail.com
> <mailto:marius...@gmail.com>> wrote:
>
>
> I think I am aware what you meant ... If you want to make SiteMap to
> know how to render itself as <ul>/<li> hence "centralize" this fine by
> me. I have nothing against it, I just don't see the need ... the good
> news is that it may be just me ;)
>
> The analogy with chooseTemplate is not very relevant IMHO because
> choseeTemplate is a construct that one can use in many application
> context whereas SiteMap is typically only one. But by all means don't
> let me stay in your way:)
>
> If you are implementing this in SIteMap then perhaps you should make
> both Menu built in snippet and MenuWidget to use it?
>
> Br's,
> Marius
>
> On Mar 21, 5:41 pm, Derek Chen-Becker <dchenbec...@gmail.com

Derek Chen-Becker

unread,
Mar 23, 2009, 12:07:13 PM3/23/09
to lif...@googlegroups.com
OK, I've pushed the new code on the wip-dcb-dropdown branch. I made some minor mods to the builtin Menu snippet (and changes to the Menu widget to match):

    1. Added an "expandAll" attribute that renders the entire SiteMap.
    2. Added a new "top" prefix to the builder snippet to allow for
       attributes on the top-level menu UL element.
    3. Added API documentation to the Menu class.

For some reason, the branch isn't showing up on github. I did a

git push origin wip-dcb-dropdown

And it says it's up-to-date, but I'm not seeing it on github.

Derek

marius d.

unread,
Mar 23, 2009, 1:18:50 PM3/23/09
to Lift
Cool ... if you tested it and the MenuWidget, from my perspective it
is good to go into master. And it's really great that you added the
ScalaDocs !!!

Br's,
Marius

On Mar 23, 6:07 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> OK, I've pushed the new code on the wip-dcb-dropdown branch. I made some
> minor mods to the builtin Menu snippet (and changes to the Menu widget to
> match):
>
>     1. Added an "expandAll" attribute that renders the entire SiteMap.
>     2. Added a new "top" prefix to the builder snippet to allow for
>        attributes on the top-level menu UL element.
>     3. Added API documentation to the Menu class.
>
> For some reason, the branch isn't showing up on github. I did a
>
> git push origin wip-dcb-dropdown
>
> And it says it's up-to-date, but I'm not seeing it on github.
>
> Derek
>
> On Sat, Mar 21, 2009 at 3:04 PM, Charles F. Munat <c...@munat.com> wrote:
>
>
>
> > +1
>
> > I am understanding exactly what you have in mind and think it's a great
> > idea. I wrote some kludgy code months ago (I knew zero about Scala back
> > then -- now I know *infinity* times more! :-) to do pretty much the same
> > thing, and I ended up completely rewriting the Menu snippet to my own
> > needs. More flexibility == good, I think.
>
> > Chas.
>
> > (For anyone a little slow on the uptake this fine Saturday, please note
> > that anything times zero is still zero.)
>
> > Derek Chen-Becker wrote:
> > > I think I'm not being very clear. I'm going to modify the builtin Menu
> > > snippet, not SiteMap. In my view, SiteMap should not be concerned with
> > > how it's rendered, but the builtin snippet surely should be able to
> > > handle this. Once I have the Menu snippet modified, the MenuWidget class
> > > would just embed a <lift:Menu.builder expandAll="true" /> tag where it
> > > wants the menu. I'll work on it this weekend and let you know when I
> > > have something usable.
>
> > > Derek
>

DavidV

unread,
Mar 31, 2009, 4:48:12 PM3/31/09
to Lift
I would like to use this new MenuWidget, so I got the source code from
GitHub and put it into my application as a snippet. I also downloaded
all of the necessary superfish .css and .js files from the superfish
website and put those in local sub-directories of the "src/main/
webapp" folder. When I try to compile the code in maven, however, I
get the following error.

C:\Source\trunk\eclipse\testLift>mvn clean jetty:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO]
------------------------------------------------------------------------
[INFO] Building testLift
[INFO] task-segment: [clean, jetty:run]
[INFO]
------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory C:\Source\trunk\eclipse\testLift\target
[INFO] Preparing jetty:run
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [yuicompressor:compress {execution: default}]
[INFO] jquery.hoverIntent.js (4637b) -> jquery.hoverIntent.js (0b)[0%]
[INFO] superfish.js (3837b) -> superfish.js (0b)[0%]
[INFO] entryform.css (11417b) -> entryform.css (10202b)[89%]
[INFO] print.css (1341b) -> print.css (821b)[61%]
[INFO]
------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO]
------------------------------------------------------------------------
[INFO] Illegal group reference
[INFO]
------------------------------------------------------------------------
[INFO] Trace
java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
at com.yahoo.platform.yui.compressor.CssCompressor.compress
(CssCompresso
r.java:78)
at
net.sf.alchim.mojo.yuicompressor.YuiCompressorMojo.processFile(YuiCom
pressorMojo.java:182)
at net.sf.alchim.mojo.yuicompressor.MojoSupport.processDir
(MojoSupport.j
ava:151)
at net.sf.alchim.mojo.yuicompressor.MojoSupport.execute
(MojoSupport.java
:105)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo
(DefaultPlugi
nManager.java:451)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(Defa
ultLifecycleExecutor.java:558)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLi
fecycle(DefaultLifecycleExecutor.java:499)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.forkProjectLifecy
cle(DefaultLifecycleExecutor.java:924)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.forkLifecycle(Def
aultLifecycleExecutor.java:767)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(Defa
ultLifecycleExecutor.java:529)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandalone
Goal(DefaultLifecycleExecutor.java:512)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(Defau
ltLifecycleExecutor.java:482)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHan
dleFailures(DefaultLifecycleExecutor.java:330)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmen
ts(DefaultLifecycleExecutor.java:291)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute
(DefaultLi
fecycleExecutor.java:142)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:
336)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:
129)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:287)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced
(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode
(Launcher.java:430)

at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
[INFO]
------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Tue Mar 31 17:38:35 EDT 2009
[INFO] Final Memory: 17M/30M
[INFO]
------------------------------------------------------------------------


Any ideas on how to prevent/fix this? Do I need to modify my .pom?

Thanks,
David

On Mar 23, 12:18 pm, "marius d." <marius.dan...@gmail.com> wrote:
> Cool ... if you tested it and theMenuWidget, from my perspective it
> > > >     both Menu built in snippet andMenuWidgetto use it?

Derek Chen-Becker

unread,
Apr 1, 2009, 8:52:21 AM4/1/09
to lif...@googlegroups.com
Based on this part of the stack trace:

java.lang.
IllegalArgumentException: Illegal group reference
       at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
       at com.yahoo.platform.yui.compressor.CssCompressor.compress
(CssCompresso
r.java:78)

I'm guessing that it's unhappy with one of your CSS files.

Derek

marius d.

unread,
Apr 1, 2009, 12:04:48 PM4/1/09
to Lift
Is there a reason why you downloaded he scripts separately? ... the
superfish dependencies are offered by the widget. Please see the lift-
widgets project and the test applicaiton from there.


Br's,
Marius
> ...
>
> read more »

DavidV

unread,
Apr 2, 2009, 5:13:55 PM4/2/09
to Lift
I posted this yesterday but I haven't seen it appear yet...sorry if it
is here twice.

I downloaded the scripts separately because I didn't know how to
update my repository/library to include the MenuWidget class and the
appropriate .js and .css files. I tried running "mvn install" on my
webapp, but it didn't download those new files.
I fixed the problem with my .css file so it compiles now, however I'm
still not getting the nice stylish superfish navbar. Instead, I'm
getting a vertical bulleted list of links to my different pages. I
think it's a problem with my template. Here are the relevant
sections:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://
liftweb.net/">
<head>
<meta http-equiv="content-type" content="text/html;
charset=UTF-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />

<title>My WebApp <lift:Menu.title /> </title>
<lift:StyleSheet.entryForm />
<lift:StyleSheet.fancyType />
<script id="jquery" src="/classpath/jquery.js" type="text/
javascript"/>
<script id="json" src="/classpath/json.js" type="text/javascript"/
>

</head>
<body>

<div class="container">
<div style="text-align: center">
<br/>
<h1 class="alt">
Welcome to My WebApp </h1>
</div>
<hr/>

<div>
<lift:MyMenu.render />
<div>
<lift:Msgs/>
<hr class="space" />
</div>
</div>


MyMenu is the snippet that contains the render method, which looks
like this:

def render(xhtml: NodeSeq): NodeSeq = {
MenuWidget(MenuStyle.NAVBAR)
}

Does anyone see what might be wrong here?

Thanks,
David



On Apr 1, 11:04 am, "marius d." <marius.dan...@gmail.com> wrote:
> Is there a reason why you downloaded he scripts separately? ... the
> superfish dependencies are offered by the widget. Please see the lift-
> widgets project and the test applicaiton from there.
>
> Br's,
> Marius
>
> On Mar 31, 11:48 pm, DavidV <david.v.villa...@gmail.com> wrote:
>
> > I would like to use this newMenuWidget, so I got the source code from
> ...
>
> read more »

Derek Chen-Becker

unread,
Apr 3, 2009, 12:07:44 AM4/3/09
to lif...@googlegroups.com
Do you have lift-widgets module as a dependency in your pom.xml?

    <dependency>
      <groupId>net.liftweb</groupId>
      <artifactId>lift-widgets</artifactId>
      <version>1.1-SNAPSHOT</version>
    </dependency>

That's needed to get the dropdown widget code.

Derek

DavidV

unread,
Apr 3, 2009, 2:36:30 PM4/3/09
to Lift
I added the dependency to my pom.xml exactly as you suggested and I'm
getting this error:

Downloading: http://scala-tools.org/repo-releases/net/liftweb/lift-widgets/1.1-S
NAPSHOT/lift-widgets-1.1-SNAPSHOT.jar
[INFO]
------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO]
------------------------------------------------------------------------
[INFO] Failed to resolve artifact.

Missing:
----------
1) net.liftweb:lift-widgets:jar:1.1-SNAPSHOT

Try downloading the file manually from the project website.

Then, install it using the command:
mvn install:install-file -DgroupId=net.liftweb -DartifactId=lift-
widgets -
Dversion=1.1-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file

Alternatively, if you host your own repository you can deploy the
file there:

mvn deploy:deploy-file -DgroupId=net.liftweb -DartifactId=lift-
widgets -Dv
ersion=1.1-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -
Drepositor
yId=[id]

Path to dependency:
1) testLift:testLift:war:1.0
2) net.liftweb:lift-widgets:jar:1.1-SNAPSHOT

----------
1 required artifact is missing.

for artifact:
testLift:testLift:war:1.0

from the specified remote repositories:
scala-tools.org (http://scala-tools.org/repo-releases),
central (http://repo1.maven.org/maven2)


I changed the dependency version to 1.0 because I followed the scala-
tools.org link (http://scala-tools.org/repo-releases) and noticed that
there wasn't a 1.1-SNAPSHOT version in net\liftweb\lift-widgets.
Maven then compiled the project, but my menu still isn't showing up as
I would like it to. I haven't changed my template.

On Apr 2, 11:07 pm, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> Do you have lift-widgets module as a dependency in your pom.xml?
>
>     <dependency>
>       <groupId>net.liftweb</groupId>
>       <artifactId>lift-widgets</artifactId>
>       <version>1.1-SNAPSHOT</version>
>     </dependency>
>
> That's needed to get the dropdown widget code.
>
> Derek
>
> ...
>
> read more »

Josh Suereth

unread,
Apr 4, 2009, 12:05:08 AM4/4/09
to lif...@googlegroups.com, Lift
Don't know if anyone responded, but you may need to add the maven
snapshot repository to your pom as well.

Sent from my iPhone

Derek Chen-Becker

unread,
Apr 4, 2009, 3:14:52 PM4/4/09
to lif...@googlegroups.com
That's probably it. Please let us know if adding the snapshots repo doesn't fix it.

Derek
Reply all
Reply to author
Forward
0 new messages