A better select one or many

April 7, 2008

“Better” is an exaggeration. It may be that occasionally it is more appropriate.

At issue is presenting a control to the user where she can select one of many, or several of many. When the selection is fairly small (arbitrary at 7 items) – radio and checkbox groups are standard. But when the choice number goes over a certain number, there are various mechanisms to be seen, of which the most common are single select <select /> and multiple select <select /> – the problem is how to fit large number of choices into a cramped area.

This came up in the context of the Sakai Course Evaluation tool, where any number of question types need to be constructed and presented to the user. One of these questions, used in a Cambridge course evaluation, involved a really long list of choices.

Occasionally you might want a control that is a bit friendlier and stylable than a <select />. A colleague alerted me to: http://c82.net/posts.php?id=25

Here is an example from C82:

Nice! The clickable area indicated by the dark green hover is created by the <label /> element, wrapping the <input /> and the text and set to display:block. The height and width of the top container (a <ul />) are fixed and the overflow:auto for the scroll.

There are three possible improvements to the excellent widget.

  1. Having the overflow and height attributes set only if the height goes over a certain number (template or system set) – so scrollbars appear after a certain height, and groups of less than that height size automatically.
  2. Having the “checked” attribute of the input reflected in the style of the parent label
  3. Having a message display of the “you have made x selections” or something like that.

Setting the scroll and height dynamically

The markup looks like this:

<ol class="multchoiceholder">
<li>
<label for="1">
<input value="1" name="1" id="1" type="checkbox">
</label>
</li>
<li>
<label for="2">
<input value="2" name="2" id="2" type="checkbox">
</label>
</li>
(etc)
</ol>

And the CSS is pretty much what the C82 article above is using, except no height is set for the container, allowing it to grow to fit the contents. To get the “intelligence” about the height I added jquery.js to the <head />

<script src="jquery.js" language="JavaScript" type="text/javascript">

And the following at the end of the document:

<script type="text/javascript">
$(".multchoiceholder").each(function(){
if ($(this).height() > 180) {
// if ($(this).children("li").size()  >  9) {
$(this).addClass("oversize")
}
})
</script>

This essentially adds the “oversize” class to the parent container if the parent container contents go over 180 pixels in height. This class, below, sets the height and the overflow that we need. I played around with counting the <li /> child nodes (commented above), but since a given list item could span multiple lines the pixel height seemed best.

ol.oversize{
border: 1px solid #ccc !important;
height: 12em !important;
overflow: auto !important
}
Advertisements

Setting up a Sakai toolbar and styling it

March 13, 2008

See Previous post: Marking Up the Sakai ToolBar.

Setting up a toolbar will depend on the templating technology. Velocity based tools will be using the #menu macro. JSF tools will be using either the ToolBar and ToolBarItem tags, or just the ToolBar + valid JSF tag children. Hand crafted markup should follow the same pattern:

<ul role=”menu” class=”navIntraTool actionToolBar”>
 <li role=”menuitem” class=”firstToolBarItem”>
  <span>
   <a href=”#”>A link</a>
  </span>
 <li role=”menuitem”>
  <span aria-disabled=”true” class=”inactive”>A string</span>
 </li>

 <li role=”menuitem”>
  <span>
   <a href=”#”>A link</a>
  </span>
 </li>
</ul>

Styling this markup offers many possibilities since it is sstandard markup for toolbars and navigation lists. See the absurdly rich Listamatic for options.

The default Sakai (as of today) rendering uses the following CSS:

/*toolbar - turn into a list for 2.6 - default list render here, style in tool.css*/
.navIntraTool li{
     list-style: none;
     display: inline;
     margin:0 !important;
     padding:0 !important;
}
.navIntraTool li span a{
     margin:0 !important;
     padding:0 !important;
}
.navIntraTool li span a img{
     vertical-align: bottom;
}
.navIntraTool li span,
  .navIntraTool li span.current,
  .navIntraTool li span.inactive{
     border-left:1px solid #ccc;
     margin:0;
     padding:0 5px 0 8px
}
/*special style for the first item, namely no border-left*/
.navIntraTool li.firstToolBarItem span{
     border:none;
     margin:0;
     padding: 0 5px 0 8px;
}
/*some toolbars have input type=text, and the next
   item (fieldSibling) is a submit link*/
.navIntraTool li span.formItem,
   .navIntraTool li span.fieldSibling  {
     margin:0;
     border:none;
     padding:0;
}
.navIntraTool li span.fieldSibling {
     padding: 0 5px 0 0;
}

/*style for item that would be a link
   if you were not at the page already*/
.navIntraTool li span.current{
     color:#777;
}
.navIntraTool li span.inactive{
     color:#777;
}

And this is what it looks like in th e Chat tool:

Default Sakai Style

Not much to note, is so simple. The “pipe” is actually the left border of the <span>. The first element does not get one. The end.

For something a bit more different here is the CSS (am just including the selectors that have changed from above).

ul.navIntraTool{
     background:#eee;
     padding: 5px !important
}.navIntraTool li span a, .navIntraTool li span a:visited,
   .navIntraTool li span a, .navIntraTool li span a:hover{
     color:#000;
     margin:0 !important;
     padding:0 !important;
     text-decoration: none !important
}

.navIntraTool li span, .navIntraTool li span.current,
   .navIntraTool li span.inactive,
   .navIntraTool li.firstToolBarItem span{
     border-top:1px solid #aaa;
     border-right:1px solid #333;
     border-bottom:1px solid #333;
     border-left:1px solid #aaa;
     margin:0;
     padding:3px 5px 3px 5px;
     background: #ddd
}
/*style for item that would be a link if you were
    not at the page already, and for inactive links*/

.navIntraTool li span.current, .navIntraTool li span.inactive{
     color:#777;
     border:1px solid #ddd;
     background: transparent;
}

toolbar-redmond.jpg

You can use a background image:

.navIntraTool li span, .navIntraTool li span.current,
    .navIntraTool li span.inactive, .navIntraTool li.firstToolBarItem span{
       border-top:1px solid #aaa;
       border-right:1px solid #333;
       border-bottom:1px solid #333;
       border-left:1px solid #aaa;
       margin:0;
       padding:3px 5px 3px 5px;
       background: #ddd url(default/images/tb-bk1.gif) top left repeat-x
}

toolbar-redmond2.jpg

Etc…… I think the markup now is fairly adaptable style wise. The examples above have just used one of the available canvases – the <span>, a lot more rich possibilities offer themselves if you want to style the four that are available to you (ul > li > span > a)….


Marking Up the Sakai ToolBar

March 11, 2008

Most Sakai apps use a toolbar to navigate between the different views
of a tool and also to initiate new actions (create an Announcement, for example).

Eons ago in a more innocent age this seemed perfectly adequate markup to express this toolbar:

 <div clas="navIntraTool">
   <a href="#">A link</a>
   <a href="#">A link</a>
   <a href="#">A link</a>
 </div>

    But it has been getting rather long in the tooth. Certain needs cropped up that made it inadequate: need for “inactive” or “current” items (instead of links), pipe separators, icons associated with a link, css styling needs that went beyond the two box (div + a) canvas, etc. This is the new structure.

    <ul clas="navIntraTool actionToolBar">
     <li class="firstToolBarItem">
      <span>
       <a href="#">A link</a>
      </span>
     </li>
     <li>
      <span class="inactive">A string</span>
     </li>
     <li>
      <span><a href="#">A link</a></span>
     </li>
    </ul>

      This needs a bit of explanation.

      1. Recasting the toolbar as an unordered list makes more sense, sure. The doubled up class name is a transitional method to take style attributes to a more consistent, less organic and crufty naming scheme that reflects function. See the complete list of proposed changes
      2. The spans are there as styling shims, that is perhaps redundant, but somewhat standard. They also serve as a locale for the inactive and current classes.
      3. The first item is classed separately class="firstToolBarItem" as an aid to CSS1 crippled browsers. Imagine that you wanted to do something different to the first item. In a perfect world you would do something like .navIntraTool > li:first-child {color:red} in the css. In this sub-lunar IE6 world your markup needs to flag the first item so that you can address it in the css as .navIntraTool .firstToolBarItem {color:red}

      While at it – what more would the toolbar menu need? In a leap of faith and talking it over with Colin and Eli decided that WAI roles and states might make sense. Since this work is slated for Sakai 2.6, opted for a future version W3C WD, rather than the current one. The benefits (beyond future proofing) are that no namespace declarations are required, is less verbose.

      <ul role="menu" class="navIntraTool actionToolBar">
       <li role="menuitem" class="firstToolBarItem">
        <span>
         <a href="#">A link</a>
        </span>
       <li role="menuitem">
        <span aria-disabled="true" class="inactive">A string</span>
       </li>
       <li role="menuitem">
        <span>
         <a href="#">A link</a>
        </span>
       </li>
      </ul>

        Having decided on this, changing the tools based on the Velocity engine was fairly trivial. Most used a macro in the macro library to render the toolbar. The tricky parts involved figuring out which of the items was the first so that we could add the pesky class, which were disabled, which where a formish input toolbar item (there are a few of those).

        A handful of Velocity based tools had hand coded toolbars – it was just a matter of changing their templates, tedious but simple. A few involved yet more wrangling to decide if given a user and a state a given toolbar item was the first in the series or not.

        Changing the toolbar for the JSF based tools (that made use of the tag!!) was also fairly trivial. Two tags were involved: ToolBar and ToolBarItem (these are the renderers). As much as I complain about Sakai’s JSF, this was pretty sweet.

        Next, the Sakai tools that used JSF but did not use those particular tags. I expected a lot of hand coded markup and inventiveness, as the two Sakai JSF tags were not very flexible. Such as as this hybrid:

        <sakai:tool_bar>
         <h:commandLinkaction="#{ChatTool.processActionSynopticOptions}"
             rendered="#{ChatTool.maintainer}">
          <h:outputText value="#{msgs.manage_tool}" />
         </h:commandLink>
        </sakai:tool_bar>

          This toolbar uses the tag <sakai:tool_bar> to set up the outer container, then a set of JSF commandLinks (instead of the ToolBarItem tag). What to do? With the new tag the outer container as a <ul>, and the commandLinks translated to <a> giving us:

          <ul class="navIntraTool actionToolBar">
           <a href="#">A link</a>
           <a href="#">A link</a>
           <a href="#">A link</a>
          </ul>

            What was needed was a way to insert the list item, first item class, the span shim, a class for the inactive shim. Cringing from the first thing that occurred to me (a tag soup of <f:verbatim>) I noticed that this particular tool uses the excellent MyFaces Tomahawk components. The solution then was:

            <t:htmlTag rendered="#{ChatTool.maintainer}"
             value="ul"styleClass="navIntraTool actionToolBar">
             <t:htmlTag value="li"  styleClass="firstToolBarItem">
              <t:htmlTag value="span">
               <h:commandLinkaction="#{ChatTool.processActionSynopticOptions}">
                <h:outputText value="#{msgs.manage_tool}"/>
               </h:commandLink>
              </t:htmlTag>
             </t:htmlTag>
            </t:htmlTag>

              I love the <t:htmlTag> and want to take it home and keep it as a pet!! Even if it feels slightly funny to use it.

              It occurred to me that I could modify the Sakai JSF tags so they would do the right thing even if the child element were not a ToolBarItem – so that is what I will be doing instead. Any valid (h:outputLink, h:commandButton,h:commandLink) JSF child tag of ToolBar will be wrapped appropriately.

              Note: the new renderers ignore the “separator” attribute. This is no longer needed, of course, as the items are list items and you can plonk any sort of visual separator you could possibly want via CSS. Hand coded JSF markup does not get the ARIA state attributes either (because a commandLink has no notion of “disabled”, for example, that the toolBarItem tag can do stuff with).

              The Gradebook tool, for example does the following:

              <h:commandLink action="#{bean.navigateToOverview}"
                  immediate="true" rendered="#{bean.pageName ne 'overview'
                  && bean.breadcrumbPage ne 'overview'}">
                     <h:outputText value="#{msgs.appmenu_overview}"/>
                     <f:param name="pageName" value="overview" />
              </h:commandLink>
              <h:outputText value="#{msgs.appmenu_overview}" escape="false"
                   rendered="#{bean.pageName eq 'overview' || bean.breadcrumbPage eq
                   'overview'}" styleClass="currentView" />

              That is – it uses an <h:outputText /> if you are “there” – the problem is that this resolves to to a <span>. When this runs via ToolBarItem you get:

              <li>
                <span>
                  <span class="currentView">
                     String
                  </span>
                </span>
              </li>

              With the new tags it is possible to avoid this by having the inactive “you are here” string output via a ToolBarItem with a “disabled=’true'” attribute.

              Other exotic uses of the ToolBar tag are the following. In most cases this seems to involve poking in an h:commandLink with maybe an h:grapicImage child of that, but I will need to test them all. I have not checked this in yet to trunk.

              msgcntr\messageforums-app\src\webapp\jsp\
              discussionForum\message\dfFlatView.jsp(35)

              This seems ok.

              msgcntr\messageforums-app\src\webapp\jsp\
              discussionForum\forumsOnly\dfForums.jsp(23)

              looks standard

              msgcntr\messageforums-app\src\webapp\jsp\
              discussionForum\message\dfViewMessage.jsp(90)

              has a child: <h:panelGrid columns=”2″ width=”100%” summary=”layout”> the solution is to get rid of the panel grid…. (create patch)

              msgcntr\messageforums-app\src\webapp\jsp\
              discussionForum\message\dfViewThread.jsp(24)

              should be ok

              msgcntr\messageforums-app\src\webapp\jsp\
              privateMsg\addAttach.jsp(12)

              ???

              <sakai:tool_bar>
               <sakai:tool_bar_message
                 value="Attachment from a Local File" />
               </sakai:tool_bar>

              looks like this will resolve to an h3 inside a toolbar. Problem, but cannot find where used.

              msgcntr\messageforums-app\src\webapp\jsp\
              privateMsg\pvtMsgHpView.jsp(29)

              another panelGrid and tool_bar mashup – create patch

              osp\presentation\tool\src\webapp\freeForm\
              arrange.jsp(19)

              <sakai:tool_bar>
                <h:selectOneMenu value="#{freeForm.currentPageId}">
                  <f:selectItems value="#{freeForm.pageDropList}" />
                </h:selectOneMenu>
                <h:commandButton value="#{msgs.change_arrange_page}"
                    action="#{freeForm.processChangeCurrentPage}" />
              </sakai:tool_bar>

              not sure where this is used. Most of osp/presentation is spring mvc jsp.

              reports\reports-tool\tool\src\webapp\reports\main.jsp(8)

              <sakai:tool_bar>
                <h:commandLink rendered="#{ReportsTool.maintainer}"
                   action="#{ReportsTool.processPermissions}">
                  <h:outputText value="#{msgs.permissions_link}"/>
                </h:commandLink>
                <h:outputText value="#{'   |   '}" escape="false"
                   rendered="#{ReportsTool.maintainer}"/>
                <h:commandLink rendered="#{ReportsTool.maintainer}"
                   action="#{ReportsTool.processImportDefinition}">
                   <h:outputText value="#{msgs.import_report_def}"/>
                </h:commandLink>
              </sakai:tool_bar>

              Looks ok, create patch.
              syllabus\syllabus-app\src\webapp\syllabus\add_attach.jsp(15)

              <sakai:tool_bar>
                <sakai:tool_bar_message
                  value="#{msgs.title_add_attach_local}" />
              </sakai:tool_bar>

              This will not work, deprecated?

              syllabus\syllabus-app\src\webapp\
              syllabus\main.jsp(33)

              custom <syllabus:syllabus_ifnot> tag needs to be changed with something else, commandLinks with working rendered attributes, for example.

              syllabus\syllabus-app\src\webapp\syllabus\
              multi_delete_confirm.jsp(33)

              nekkid <sakai:tool_bar_item> tags inside a table. Deprecated?

                More later on managing the styling of what is now 2 different markup toolbar blobs on Sakai (old and new). And examples on styling it as well!