Using/Configuring the Sakai Rich Text Editor

March 22, 2008

The rich text editor in Sakai has a very hard row to hoe. It needs to be:

  1. invoked in the context of 6 view technologies (Velocity, JSF, SPRING/MVC/JSP, XSLT, RSF, Servlets, am sure am forgetting some!)
  2. configured to run plugins (Sakaibrary, Josh Ryan’s Entity Browser, etc.) or not
  3. stand being poked into a number of curious contexts, fulfilling any number of disparate purposes, from helping people write smallish blurbs, blog entries, full blown web pages, the Encyclopedia Galactica, etc.
  4. display in tight spaces, take over the whole screen, stuff in between…
  5. be any rich text editor – the tool invoking it need not know what rich text editor is being invoked – FCK, HTMLArea, TinyMCE, etc.

This is what it looks like at present (FCKEditor used as example below). This is default, when no parameters are specified it resolves to an editor area 600px wide, 400px tall, with the Default ToolbarSet.

default.png

In the Velocity tools the editor is invoked via a daisy chain of macros and templates. Unfortunately the only parameter that makes to the actual editor script is the id of the textarea being replaced. Am addressing that in SAK-13244.

Sakai tools that use Velocity will have the following in a template:

<textarea name="body" class="block" id="body"
  cols="65" rows="30" wrap="virtual">
</textarea>
 #chef_setupformattedtextarea("body")

The #chef_setupformattedtextarea macro lives in VM_chef_library.vm:

#macro (chef_setupformattedtextarea $textarea_id)
  ## setup wysiwyg editor
  #set($editor_path = "vm/editor/$!sakai_editor/sakai_body.vm")
  <!-- $editor_path -->
  #parse("$editor_path")
  <script type="text/javascript" defer="1">
   chef_setupformattedtextarea('$textarea_id');
  </script>
#end

and essentially uses a server variable ($!sakai_editor) to decide on the rich text editor that the installation is using, then calls a text editor specific template (vastly simplified below) that sets up some configuration values:

function chef_setupformattedtextarea(textarea_id){
  var oFCKeditor = new FCKeditor(textarea_id);
  oFCKeditor.BasePath = "#libraryLink("editor/FCKeditor/")";
  <snip />
  oFCKeditor.Width  = "600" ;
  oFCKeditor.Height = "400" ;
  oFCKeditor.Config['CustomConfigurationsPath']
    = "#libraryLink("editor/FCKeditor/config.js")";
  oFCKeditor.ReplaceTextarea() ;
}

The thing to notice is that the only value passed along the chain is the id of the textarea in the template that will be replaced with the editor. What values would be minimally useful other than that? I decided arbitrarily that width, height and editor toolbar options would be the most useful. I wonder if this is true.

So now the calling template has:

#chef_setupformattedtextareaparams("description" "400"
  "600" "Default")

and the macro in VM_chef_library.vm reads:

#macro (chef_setupformattedtextareaparams $textarea_id
 $height $width $ToolBarSetChoice)
 <snip />
 <script type="text/javascript" defer="1">
   chef_setupformattedtextarea('$textarea_id','$height',
    '$width','$ToolBarSetChoice');
 </script>
#end

Note that there is a new macro involved (chef_setupformattedtextareaparams). The old one (chef_setupformattedtextarea) expects one parameter only. Velocity macros cannot deal with missing parameters, so need 2, one macro that expets one parameter (the id of the textarea) and another that expects exactly four.

The template that drops the javascript onto the the template DOM is would use the paramenters if available and provide some defaults if not.

Height and width are pretty self explanatory, toolbar settings are trickier. FCKEditor allows for named bundles of toolbar functionality – out of the box is provides “Default,” “Attachments,” and “Basic.” To these I have added the following: “large”, “medium” and “small” described below. These names were adopted because they are the same as the ones used in the HTMLArea option. Since a given bundle has certain horizontal needs I indicate the width sweetspots for each.

small

365 px wide or more. This essentially is the FCK “Basic” plus some added functionality. The emphasis is on writing text, without too much block formatting (other than lists), and no non-textual elements. Suitable for comments, quick text entries, snippets of all types.

sakai-min.png

medium

410px wide or more. Is like small + links to word processing like functionality (copy, paste, undo, search) as well as embedding,linking and extended formatting options.
sakai-med.png

large

At 410 it will display 5 rows in the toolbar, at 500px will display 4 and at 600 it will display 3. Essentially the FCK “Default” minus some functionality and rearranged somewhat for more width elasticity.

sakai-max.png

largecompressed

Same set of options as large but toolbar will fit in small areas – 380px wide, for example.

The choices above can be seen as arbitrary. I will try to get feedback on them. Ideally the user could swap between choices, but at the very least we can provide some useful defaults.

Next – invoking and configuring the editor in JSF, as well as the problem of multiple parameter types for some options such as the toolbar options in various editors.

JSF invocation

There are 2 tags available. <sakai:inputRichText /> and <sakai:rich_text_area />.

sakai:inputRichText:

presentation parameters: width, height (integers, in pixels), cols, rows (integers – some conversion to actual height and width takes place in the tag), toolbarButtonRows (integers, or string – in the later case it is a named set of buttons sets: “small”, “medium”,”large” and “largecompressed” )

sakai:rich_text_area:

presentation parameters: width, height (integers – in pixels), cols, rows (integers – some conversion to actual height and width takes place in the tag), buttonSet (string – the values are “small”, “medium”,”large” and “largecompressed”)

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!