Forum OpenACS Development: Breadcrumb trail service?

Collapse
Posted by Michael Feldstein on

One thing that ACS has always used since the days when Philip was the guiding light has been the breadcrumb trail for navigation. But it's not clear to me that there's a simple and unified way of generating the breadcrumb trail (and the implicit navigation tree behind it) for a whole site. Perhaps there is something like this in OpenACS 4 and I just don't know it.

What I would like to see is something like the following:

  • Using something like the site map utility, application packages could generate their own breadcrumb trails.

  • There would also be a mechanism to automagically add breadcrumb trails to static pages within the site, maybe based on where they are in the physical file system.

  • There would be an admin page for non-programmers where they could do things like change the root of the trail from "Your Workspace" to the home page, etc.

  • There would be some kind of utility by which the site's organizational tree that is implicit in the breadcrumb trail could be made available to an application (to be developed later) that could generate site maps, hierarchical menus, and so on.

How far are we from having something like this and how hard would it be to make it?

Collapse
Posted by Don Baccus on
[Open]ACS 4 is no better in this regard than earlier versions of the ACS, and you've identified a real problem.  Programmers build these "by hand" with some help from procedures that know something of the site map structure.  As you've noticed from [Open]ACS 3.x the nav bars aren't consistent in how they build up the string of nav links (the "crumbs").

This is largely due to the fact that they're built "by hand" by programmers who don't always do things consistently.  As the toolkit's matured, the nav bars have become more consistent but that's due to sweaty work, not automated help.

For my birdnotes.net site I developed a scheme that works very well for automatically generating the proper nav bars, but it depends upon - and generates - very, very ugly URLS with a lot of garbage encoded into them.  We need a better scheme, long-term, for OpenACS 4.x and I'm open to suggestion.

Despite the ugliness of the URLs my scheme generates, the basic notion
I implemented is easy to use.  Each time you enter a page you do an "update_context_bar" with the variables needed to regenerate the page, and there are procs to generate links with popped-off context bar data
so pages automatically point back to where you came from, rather than a fixed set of links.  Something along these lines could interact with
ad_page_contract (which could generate the context bar) in the more general environment implemented by the ACS in the days since I wrote my hack (based on ACS 1.x).

Cookies are invisible but users don't like cookies and we really only want to use them for users who are logged in.  Encoding short values in the URL that map to session state data  in the db might be the most practical approach.  Ugly URLs like I use on my birdnotes.net site are
not an acceptable solution for a general toolkit, unfortunately.

Collapse
Posted by kapil thangavelu on
hmm.. how is a basic breadcrumb different than taking the url
dropping the query string, splitting on '/' and adding links to
previous elements (minus trailing)??

isn't sitemap possible just from looking at the site nodes table or
better the in memory nsv?

Collapse
Posted by Dave Bauer on
Should the breadcrumb trail reflect the visitor's current location in the site map, or the path he took to get there? This is a fine distinction, but I think depending on the answer totally changes the way it is handled.
Collapse
Posted by Don Baccus on
In birdnotes.net I took the view that it should follow the path the user took to get there.  This requires some care, i.e. stripping off elements when you skip around in order to maintain the navbar in a hierarchical form.  You can't really use the navbar as a history bar reflecting the entire path the user's entered, but you can (for instance) remember whether or not the user got to an "edit" page from the "bar" package or the "foo" package and build the navbar accordingly.

Working just off the site map doesn't work for the other style, either, as you want nav bars like:

... | New Post | Confirm New Post

where the "new post" and "confirm" pages are in the same directory within the site map.  So the site map can build the first part of a nav bar that locates you within the URL "directory" structure, but not
the last part that lets you move around files within that "directory".

And it helps even lest if you adopt the "nav bar should reflect the path the user took to get here" paradigm.

The history/back button shows me my path (to a certain lousy extent). The URL shows where I am in the site map.

I believe the bread crumb shows the state of my web application, and indicates legal (and meaningful) transitions out of that state.

For example, your visitor is in the e-commerce check-out pipeline (something like check addresses, present billing options, accept payment, verify payment, thank user...). In that pipeline you don't want to let the user take just any link away, in part because you want the user to come back and complete the purchase, in part because you want to provide guidance to the user on which steps comes next, and in part because some of those links away might wreck the state of the application (due to information being lost that wasn't incorporated in your link's exported query vars.)

In fact, I took care in the ACS 4 ecommerce port to strip all extraneous links out of the payment pipeline. And I built a special navbar that show the legal and reasonable actions so that a user could present credit card info, and still back up to change address and move forward once more.

Another viewpoint: when the context bar is rooted at /, I understand that in terms of the site map and the URL. When the context bar is rooted at my workspace, I often get confused, and think that what's "down" from my workspace are web applications that have somehow been personalized for me. It's confusing to see my-workspace : generic bboard or stuff like that.

Suggestion: when the user is navigating within a stateful web application, then the context bar should be built to reflect the meaningful states within that web application, regardless of URL or site-map.

Collapse
Posted by Dave Bauer on
So it looks like we want a system that presents a general navigation path unless there is a specific application need for a more specific solution.

That is, a template designer could call breadcrumb_trail "" and get
something based on the site map or URL path. Or they could enter something more specific to the application. I can't see any other way to produce this specific to the application without having it coded into the tcl/adp pages. I can imagine a system that packages can register a page-flow into the database or something, but that seems like a little overkill.

Collapse
Posted by Michael Feldstein on
The conventional use of breadcrumb trails is to map out a deep
site hierarchy for the user. I'm not 100% positive, but I believe it
was invented (or, at the very least) popularized by Yahoo! to solve
their problem of having an extremely deep site.

Having a breadcrumb system that maps the user's path through
the site is an interesting idea and could be useful in a number of
contexts that I can think of. However, it does function contrary to
the way users have been trained to expect breadcrumb trails to
behave.

On the other hand, if I'm understanding the technical issues with
the applications correctly, having a system that tracks the user's
path inside a specific application could, in that particular case,
actually behave (from the user's perspective) like a traditional
breadcrumb trail in the sense that it dynamically maps the page
flow (like Don's example of ... | New Post | Confirm New Post).

Whatever the mechanism used, it's important that there be a
unified reliable mechanism for mapping into an application.

Regarding the question of whether "Your Workspace" or / should
be the root of a site, it depends on how the site is set up. If "Your
Workspace" is little more than a preferences page (as it is in
most ACS sites that I've seen), then it makes more sense to root
at /. However, if "Your Workspace" is set up as a complete
personal portal page, then that's a different story. The point is
that the site admin should be able to decide on what is root from
the user's perspective.

I also don't want to lose site of the ability to map static pages.
That's an important and labor-intensive part of making a deep
and wide site navigable.

Collapse
Posted by Bruno Mattarollo on

Taken from Jakob Nielsen's website:

Structural Navigation

Do not link to all sections of the site from all pages. What is the probability that a user will go from looking at hairdryers to looking at grunge music? More to the point: what is the probability that the user will need the link on the one day in human history when he or she wants to make this transition. Why not just go back to the home page (one click to a page that is already cached and thus displays in half a second if coded correctly).

Instead, provide links to all levels of the hierarchy above the current location. Breadcrumb trails serve two purposes:

  • the context of the current page (how it is nested) allows users to interpret the page better (you don't just know that you are looking at product 354, you also know that it belongs to the widget product family)
  • the links allow users to go directly to a higher level of the site in case the current page is not what they wanted, but they do want something similar

True, users will often ignore the structural links, but sometimes they will notice them, especially when they are interested in understanding a page better. Without structural links, pages become orphans that are not contextualized. And since users often arrive at pages through search or other means that bypass the higher-level navigation pages, it is necessary to provide a path back to these higher levels. In particular, it is useful to link to a page that provides an overview of the current subsite or region.

Just my 2 cents.

Collapse
Posted by Ed Avis on
(Disclaimer: this answer is based on ACS Tcl 4.2 - but surely the ad_context_bar proc I refer to is included in OpenACS as well?)

Application packages already do create breadcrumb trails using the site map.  It's called ad_context_bar.  The best thing is to set a variable called context_bar and include it in the master ADP template so the context bar appears in the same place on each page.  Just calling ad_context_bar with one argument (the page's title) will usually do something reasonable; alternatively you can customize things a bit further by giving multiple arguments or just write the context bar by hand.

Adding a context bar to static pages - well just rename .html to .adp, make sure <master> is in there, and make a .tcl file which does nothing but set the context_bar variable.

Changing the root of the context bar: I suppose that ad_context_bar could be extended to have some configurability.  I'd be wary of doing a database hit to get the configuration data though, because it happens on every single page.

Utility to view the site map: there are probably some utility procs to do some of this already.

Collapse
Posted by Michael Feldstein on

Application packages already do create breadcrumb trails using the site map. It's called ad_context_bar. The best thing is to set a variable called context_bar and include it in the master ADP template so the context bar appears in the same place on each page. Just calling ad_context_bar with one argument (the page's title) will usually do something reasonable; alternatively you can customize things a bit further by giving multiple arguments or just write the context bar by hand.

This is awesome. Can somebody try it and see how it well it works? Are there any tweaks required to make it work more reliably? Do we need to include info about how to set this up in some kind of a style guide?

Changing the root of the context bar: I suppose that ad_context_bar could be extended to have some configurability. I'd be wary of doing a database hit to get the configuration data though, because it happens on every single page.

Is there any way to do this in a way that is less of a drag on performance? Some way to cache the info or something? It's not like this parameter is going to change very often.

Adding a context bar to static pages - well just rename .html to .adp, make sure is in there, and make a .tcl file which does nothing but set the context_bar variable.

That sounds like more work than a non-programming admin could do, unless I'm not understanding something correctly. What I'd like to see is a way that the admin could have the context bar set properly simply by uploading the pages into the proper folder or something equally easy. If we want this to be used for large sites, then no hand programming or even hand setting of per-page admin parameters should be required.

Utility to view the site map: there are probably some utility procs to do some of this already.

Ultimately, what I have in mind here is the ability for the system to dynamically generate all navigation structures, including menu bars, context bars, and site maps, from such procs. The first step in that direction is to be able to extract the hierarchy tree from whatever it is that generates the context bar and make that tree available to other applications. Would this require a service contract?

Collapse
Posted by Luke Pond on
The Edit This Page package automatically generates a context bar for every page it serves. This is done using ad_context_bar, since ETP subtopics are equivalent to package instances. The resulting html fragment is stored for you in the "pa" array variable created by etp::get_page_attributes, so your page templates need to reference @pa.context_bar@.

I chose to remove the "Your Workspace" link from the beginning of the context bar for two reasons: 1) Like Jerry, I don't really think it belongs there, and 2) Since the page attributes are cached, I didn't want a page's context bar changing depending on whether or not the user was logged in. The caching allows ETP to avoid issuing the same queries over and over for each page, and this includes the query on the site_nodes table performed by ad_context_bar.

Even better for navigational purposes, once you're using the content repository, you can write a single query that generates a dynamic hierarchical site-map to be displayed on every page. See http://ctf.museatech.net for an example. To me, this feature is one of the best arguments for storing your static content in the database.

Collapse
Posted by Stephen . on
The reason context bar is rooted at My Workspace if you are logged in is to allow users to find subsites. There may be multiple 'roots' (subsites), mounted at different points in the URL heirarchy.

Obviously this doesn't suite all (or even most..?) things you'd like to build, but it works as a default for development.

If you search /api-doc for 'context' you'll see that there are other simillar procs which differ in their inclusion or not of the My Workspace link, among other things. It doesn't look ideal though...

I modified my personal copy of acs and split the ad_context_bar proc into two. A helper proc calls the db for the site map info and returns it as a list. The main proc calls the helper and caches for a couple of minutes, which gets rid of one db hit on every page.

If you did something simillar for your ETP thing, your context bar could be somewhat dynamic again, depending on log-in status...

Collapse
Posted by Ed Avis on
Replying to Michael Feldstein's reply to my reply...

ad_context_bar doesn't need any special setting up.  Just try calling it in a Tcl page and including the output (not quoted) in the corresponding ADP.  The _best_ way to do it is to have the context bar in the site master template, so it appears in a consistent place everywhere, but that's not necessary (and not usually done at present).

About a database hit for each context bar: well I'm pretty sure that ad_context_bar will look at the database already to find out the site layout (unless it does something interesting like asking the request dispatcher (or whatever it's called)).  So another hit for configuration would not be such a big deal.  I don't think caching is necessarily a good idea; one of the principles of ACS design is not trying to outsmart the DBMS.

Adding context bars to 'static pages' is an instance of the general problem of having a static page with some small amount of dynamic stuff.  I still think that the best answer is to have a trivial Tcl file for each page and maintain the static page as ADP (which can be pretty much a plain HTML document).  If you wanted a site-wide master template for your static pages, or any other fancy effect, you'd need to use ADPs _anyway_.  They are designed to be editable with ordinary HTML tools - the only difference is <master> at the top instead of <html> etc, and one extra line @context_bar;noquote@ (or whatever it is in OpenACS).

If you wanted anything even less technical and even more friendly then you'd probably dispense with editing files altogether and go for some kind of CMS.  Of course there it is easy to make the CMS package add a context bar to each page.