YA menu question: separate menus

15 views
Skip to first unread message

Joe Wass

unread,
Jun 8, 2009, 5:06:06 PM6/8/09
to Lift
Sorry for yet another menu question. I have scoured this list first, I
promise!

I'm trying to do something I think is quite simple:

Two [or any nuumber of] menus (with children). Two different
templates. One menu and children shows up on one template, one shows
up on another. They are each nested menus (i.e. I have two Menus, each
with child menu items). You can directly go to any page you want, but
only certain Menu items show up on certain templates.

I had thought I could put a guard (the last argument of the Loc) to
only show a menu when the request string contains part of the path,
but of course, that prevents you from navigating there in the first
place so that's out.

I've seen this post :
http://groups.google.com/group/liftweb/browse_thread/thread/dbdf6a17b9704c99/30f5168e87161f74?hl=en&lnk=gst&q=new+sitemap%2Fmenu+features

but it doesn't quite do what I want: I want to be able to show a whole
Menu at a time, not have to list each individual item in the template.
I'd like to do something like this:

<lift:Menu.builder menuName="menu_name"/>

Any ideas? I'll accept a hack, I'm short on time!

Bonus marks: how do you set a menu to be expanded by default (without
having to be on the root node's page)? I saw `expandAll="true"`
somewhere, but that doesn't do anything...

Thanks!

Joe

glenn

unread,
Jun 8, 2009, 5:24:33 PM6/8/09
to Lift
I have a similar request: namely, being able to apply expandAll="true"
attribute
not just to <lift:Menu.builder.../>

but to <lift:Menu.group name="mygroup"/> and <lift:Menu.item
name="myMenu"/>, or, as Joe requests below,

to any siteMap that is not the root siteMap.

Glenn...

On Jun 8, 2:06 pm, Joe Wass <j...@folktunefinder.com> wrote:
> Sorry for yet another menu question. I have scoured this list first, I
> promise!
>
> I'm trying to do something I think is quite simple:
>
> Two [or any nuumber of] menus (with children). Two different
> templates. One menu and children shows up on one template, one shows
> up on another. They are each nested menus (i.e. I have two Menus, each
> with child menu items). You can directly go to any page you want, but
> only certain Menu items show up on certain templates.
>
> I had thought I could put a guard (the last argument of the Loc) to
> only show a menu when the request string contains part of the path,
> but of course, that prevents you from navigating there in the first
> place so that's out.
>
> I've seen this post :http://groups.google.com/group/liftweb/browse_thread/thread/dbdf6a17b...

Derek Chen-Becker

unread,
Jun 8, 2009, 6:50:16 PM6/8/09
to lif...@googlegroups.com
If I have some time tomorrow I'll look into getting both of these working. I think that with a little refactorization of the Menu.builder code into common methods that this should be pretty simple.

Derek

Joe Wass

unread,
Jun 8, 2009, 6:51:59 PM6/8/09
to Lift
What I really wanted was a menu group. Doing things in groups has
solved my particular question.

Glenn, can you not just use groups? Do you need the hierarchal
behaviour of nested menus?

Joe

glenn

unread,
Jun 8, 2009, 7:49:15 PM6/8/09
to Lift
Yes,

I would like the expandAll behavior to work for groups and for non-
root siteMaps.
Here's a specific use-case. The MenuWidget in the lift-widgets package
just passes everything
through as

def render : NodeSeq = {
head ++ <lift:Menu.builder expandAll="true" top:class=
{style.toString} />
}

So, even though the MenuWidget object has factory methods
for using a non-root siteMap, only the root siteMap is ever used.
That's
because Menu.builder calls a private function renderWhat, like so:

val toRender = renderWhat(expandAll)

which iterates through the root siteMap. There is no way, really, to
subclass that
to use a different siteMap.

The problem with the Menu.group snippet is that it just works off the
named group in
the root siteMap, creating a parent node, but not the kids.

It would be nice to use MenuWidget, or some subclass, to create a
superfish-style
nav-bar or horizontal menu for groups or non-root siteMaps just as
easily as for the
entire root siteMap.

Glenn...

Derek Chen-Becker

unread,
Jun 11, 2009, 2:54:00 PM6/11/09
to lif...@googlegroups.com
I'm building some code right now that I think should handle all of your cases. Since Menu.builder is already concerned with building a menu tree, I decided that it would be better to allow you to specify a specific item or group to Menu.builder instead of conflating tree building with the current Menu.item and Menu.group snippets. Given a SiteMap like:

    val menus =
      Menu(Loc("Home", List("index"), "Home Page")) ::
      Menu(Loc("Viewtest", List("ViewTest", "test"), "View test")) ::
      Menu(Loc("InsecureViewtest", List("Insecure", "test"), "Insecure View test")) ::
      Menu(Loc("SelectTest", List("select"), "asm select test")) ::
      Menu(Loc("Help", List("help", "index"), "Help", LocGroup("help")),
       Menu(Loc("About", List("help", "about"), "About", LocGroup("help"))),
       Menu(Loc("Version", List("help", "version"), "Version", LocGroup("help")))) :: Nil

You can render just the Help tree with:

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

Which will render something like:
<ul><li><a href="/testthis/help/">Help</a><ul><li><a href="/testthis/help/about">About</a></li><li><a href="/testthis/help/version">Version</a></li></ul></li></ul>
Similarly, you can use a group attribute:

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

But notice that this won't deduplicate entries, so we would render something like:

<ul><li><a href="/testthis/help/">Help</a><ul><li><a href="/testthis/help/about">About</a></li><li><a href="/testthis/help/version">Version</a></li></ul></li><li><a href="/testthis/help/about">About</a></li><li><a href="/testthis/help/version">Version</a></li></ul>

This is currently checked in on the wip-dcb-menu-addons branch:

http://github.com/dpp/liftweb/tree/wip-dcb-menu-addons

Thoughts?

Derek

glenn

unread,
Jun 12, 2009, 7:45:20 AM6/12/09
to Lift
Derek,

I'd love to test the changes you made to Menu, but my build fails when
I run
mvn install on the pom in the lift directory of the download from

http://github.com/dpp/liftweb/tree/wip-dcb-menu-addons

Here's what maven reports:

[WARNING] Warning in manifest for net.liftweb:lift-webkit:jar:1.1-
SNAPSHOT : Did not find matching r
eferal for org.slf4j.*
[ERROR] Error in manifest for net.liftweb:lift-webkit:jar:1.1-
SNAPSHOT : The default package '.' is
not permitted by the Import-Package syntax.
This can be caused by compile errors in Eclipse because Eclipse
creates
valid class files regardless of compile errors.
The following package(s) import from the default package
[net.liftweb.http, net.liftweb.http.auth, n
et.liftweb.http.js, net.liftweb.http.js.jquery, net.liftweb.sitemap]
[ERROR] Error(s) found in manifest configuration
[INFO]
------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO]
------------------------------------------------------------------------
[INFO] Error(s) found in manifest configuration

It seems like a problem with the construction of the following
plugin in the pom.

<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Export-Package>!
net.liftweb.util.*,net.liftweb.*;version="${pom.version}"</Export-
Package>
<Import-Package>org.slf4j.*;resolution:="optional",*</
Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>

Either that, or there's something else going on. Any ideas?

Glenn...

On Jun 11, 11:54 am, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> I'm building some code right now that I think should handle all of your
> cases. Since Menu.builder is already concerned with building a menu tree, I
> decided that it would be better to allow you to specify a specific item or
> group to Menu.builder instead of conflating tree building with the current
> Menu.item and Menu.group snippets. Given a SiteMap like:
>
>     val menus =
>       Menu(Loc("Home", List("index"), "Home Page")) ::
>       Menu(Loc("Viewtest", List("ViewTest", "test"), "View test")) ::
>       Menu(Loc("InsecureViewtest", List("Insecure", "test"), "Insecure View
> test")) ::
>       Menu(Loc("SelectTest", List("select"), "asm select test")) ::
>       Menu(Loc("Help", List("help", "index"), "Help", LocGroup("help")),
>        Menu(Loc("About", List("help", "about"), "About", LocGroup("help"))),
>        Menu(Loc("Version", List("help", "version"), "Version",
> LocGroup("help")))) :: Nil
>
> You can render just the Help tree with:
>
> <lift:Menu.builder item="Help" expandAll="true" />
>
> Which will render something like:
>
> <ul><li><a href="/testthis/help/
> <view-source:http://localhost:9090/testthis/help/>">Help</a><ul><li><a
> href="/testthis/help/about
> <view-source:http://localhost:9090/testthis/help/about>">About</a></li><li><a
> href="/testthis/help/version
> <view-source:http://localhost:9090/testthis/help/version>">Version</a></li></ul></li></ul>
>
> Similarly, you can use a group attribute:
>
> <lift:Menu.builder group="help" expandAll="true" />
>
> But notice that this won't deduplicate entries, so we would render something
> like:
>
> <ul><li><a href="/testthis/help/
> <view-source:http://localhost:9090/testthis/help/>">Help</a><ul><li><a
> href="/testthis/help/about
> <view-source:http://localhost:9090/testthis/help/about>">About</a></li><li><a
> href="/testthis/help/version
> <view-source:http://localhost:9090/testthis/help/version>">Version</a></li></ul></li><li><a
> href="/testthis/help/about
> <view-source:http://localhost:9090/testthis/help/about>">About</a></li><li><a
> href="/testthis/help/version
> <view-source:http://localhost:9090/testthis/help/version>">Version</a></li></ul>

glenn

unread,
Jun 12, 2009, 7:59:21 AM6/12/09
to Lift
My error. Ignore this. I did a mvn clean then mvn install outside
of Eclipse on the parent pom and everything worked fine.

Glenn...

Derek Chen-Becker

unread,
Jun 12, 2009, 10:06:49 AM6/12/09
to lif...@googlegroups.com
OK, let me know how your testing goes and whether the change meets your requirements.

Derek

glenn

unread,
Jun 12, 2009, 8:40:54 AM6/12/09
to Lift
Derek,

Your new Menu snippet works great. I created a superfish-style menu
using
a list of groups, like so:

object MenuWidgetEx {

def apply(groups:List[String]) = new MenuWidgetEx(groups,
MenuStyle.HORIZONTAL, JsObj()) render

def apply(groups:List[String], style: MenuStyle.Value) = new
MenuWidgetEx(groups, style, JsObj()) render

def apply(groups:List[String], jsObj: JsObj) = new MenuWidgetEx
(groups, MenuStyle.HORIZONTAL, jsObj) render

def apply(groups:List[String], style: MenuStyle.Value, jsObj:
JsObj) = new MenuWidgetEx(groups, style, jsObj) render
}


class MenuWidgetEx(groups:List[String], style: MenuStyle.Value, jsObj:
JsObj) extends
MenuWidget(LiftRules.siteMap open_!, style: MenuStyle.Value, jsObj:
JsObj){

override def render :NodeSeq = {

def buildMenu(group:String) = <lift:Menu.builder group={group}
expandAll="true" top:class={style.toString} />


head ++ <div>
{for(group <- groups) yield {buildMenu(group)}}
</div>


}

Someone should redo the MenuWidget snippet to handle your
new Menu.builder construct, so it doesn't have to be subclassed.

Glenn...

Derek Chen-Becker

unread,
Jun 12, 2009, 3:02:06 PM6/12/09
to lif...@googlegroups.com
Tied up with work this afternoon, but I'll look at reworking MenuWidget with the added functionality.

Derek Chen-Becker

unread,
Jun 19, 2009, 11:57:05 AM6/19/09
to lif...@googlegroups.com
OK, I've committed some new support for groups in the MenuWidget class. Also, the existing MenuWidget had facilities set up to take a SiteMap instance as part of the setup params, but those params were never used. In the interest of simplicity, I've removed those extra params unless someone has a use case that's not covered by groups or the other new functionality. If no one has any issues with the new code I'll merge to master later today.

Derek

glenn

unread,
Jun 19, 2009, 1:54:47 PM6/19/09
to Lift
Derek,

It does not appear that these changes have been migrated to the
snapshot repository yet.
What are you plans?

thanks,

Glenn...

On Jun 19, 8:57 am, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> OK, I've committed some new support for groups in the MenuWidget class.
> Also, the existing MenuWidget had facilities set up to take a SiteMap
> instance as part of the setup params, but those params were never used. In
> the interest of simplicity, I've removed those extra params unless someone
> has a use case that's not covered by groups or the other new functionality.
> If no one has any issues with the new code I'll merge to master later today.
>
> Derek
>
> ...
>
> read more »

Derek Chen-Becker

unread,
Jun 19, 2009, 5:49:28 PM6/19/09
to lif...@googlegroups.com
I'll merge it first thing Monday. I'm going to be in and out this weekend so I don't want to merge something that may potentially break anything.

Derek

Derek Chen-Becker

unread,
Jun 22, 2009, 12:37:59 PM6/22/09
to lif...@googlegroups.com
Pushed to master.

glenn

unread,
Jun 30, 2009, 12:44:47 PM6/30/09
to Lift
Derek,

I was out of town all last week and just tried to rebuild and run with
your
new changes, but got the following error:

ERROR - Failed to Boot
java.lang.NoSuchMethodError: net.liftweb.sitemap.SiteMap.<init>(Lscala/
Seq;)V
at bootstrap.liftweb.Boot.boot(Boot.scala:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at net.liftweb.util.ClassHelpers$$anonfun$createInvoker$1.apply
(ClassHelpers.scala:408)
at net.liftweb.util.ClassHelpers$$anonfun$createInvoker$1.apply
(ClassHelpers.scala:406)
at net.liftweb.http.DefaultBootstrap$$anonfun$boot$1.apply
(LiftRules.scala:1049)
at net.liftweb.http.DefaultBootstrap$$anonfun$boot$1.apply
(LiftRules.scala:1049)
at net.liftweb.util.Full.map(Box.scala:330)
at net.liftweb.http.DefaultBootstrap$.boot(LiftRules.scala:1049)
at net.liftweb.http.LiftFilter.bootLift(LiftServlet.scala:561)
at net.liftweb.http.LiftFilter.init(LiftServlet.scala:529)
at org.mortbay.jetty.servlet.FilterHolder.doStart(FilterHolder.java:
97)
at org.mortbay.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize
(ServletHandler.java:653)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext
(WebAppContext.java:1239)
at org.mortbay.jetty.handler.ContextHandler.doStart
(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:
466)
at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStart
(Jetty6PluginWebAppContext.java:124)
at org.mortbay.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerCollection.doStart
(HandlerCollection.java:152)
at org.mortbay.jetty.handler.ContextHandlerCollection.doStart
(ContextHandlerCollection.java:156)
at org.mortbay.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerCollection.doStart
(HandlerCollection.java:152)
at org.mortbay.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart
(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:222)
at org.mortbay.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:50)
at org.mortbay.jetty.plugin.Jetty6PluginServer.start
(Jetty6PluginServer.java:132)
at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty
(AbstractJettyMojo.java:441)
at org.mortbay.jetty.plugin.AbstractJettyMojo.execute
(AbstractJettyMojo.java:383)
at org.mortbay.jetty.plugin.AbstractJettyRunMojo.execute
(AbstractJettyRunMojo.java:210)
at org.mortbay.jetty.plugin.Jetty6RunMojo.execute(Jetty6RunMojo.java:
184)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo
(DefaultPluginManager.java:579)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures
(DefaultLifecycleExecutor.java:498)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmentForProject
(DefaultLifecycleExecutor.java:265)
at
org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments
(DefaultLifecycleExecutor.java:191)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute
(DefaultLifecycleExecutor.java:149)
at org.apache.maven.DefaultMaven.execute_aroundBody0
(DefaultMaven.java:223)
at org.apache.maven.DefaultMaven.execute_aroundBody1$advice
(DefaultMaven.java:304)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:1)
at org.apache.maven.embedder.MavenEmbedder.execute_aroundBody2
(MavenEmbedder.java:904)
at org.apache.maven.embedder.MavenEmbedder.execute_aroundBody3$advice
(MavenEmbedder.java:304)
at org.apache.maven.embedder.MavenEmbedder.execute(MavenEmbedder.java:
1)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:176)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced
(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch
(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode
(Launcher.java:408)
at org.codehaus.plexus.classworlds.launcher.Launcher.main
(Launcher.java:351)
at org.codehaus.classworlds.Launcher.main(Launcher.java:31)

When I ran the my app, all the menu links just said "No navigation
defined".
I'm using lift 1.1-SNAPSHOT out of http://scala-tools.org/repo-snapshots.
Is this where you made your changes?

Glenn...
> ...
>
> read more »

Derek Chen-Becker

unread,
Jun 30, 2009, 4:37:57 PM6/30/09
to lif...@googlegroups.com
Yes. The error you're getting looks like a version mismatch or some other dependency issue. Can you wipe ~/.m2 and try th build again?

Derek

george

unread,
Jun 30, 2009, 6:42:45 PM6/30/09
to Lift
This feature will be very useful for me also. Thanks.

However, I would like to be able to show a separate menu for the
MegaProtoUser menu items.

So it would be great if the MegaProtoUser built in menu items had some
default LocGroup set. Or if there was a way to change the LocGroup of
a Loc at runtime.

Maybe this is possible but I have missed it?

George
> > I'm using lift 1.1-SNAPSHOT out ofhttp://scala-tools.org/repo-snapshots.
> > > > > >> > > valid class files regardless of compile errors....
>
> read more »
Reply all
Reply to author
Forward
0 new messages