Skinnin’

August 23, 2010

Skinning involves an entity reformatting a bundle of functionality to make the experience of that functionality reflect it’s sense of self. When the entity is a simple one like a single human user, the task is a simple one as well. When the entity is a complex one with different parts that demand representation in the interface, things can get complicated.

I) A skinning system needs to account for different user spaces

  1. Institutional Gateway – traditionally has family resemblance to other institutional spaces. May have to obey institutional web style guides (logos, palettes, fonts)
  2. Personal spaces – can have an a) institutional branding as 1 above, b) a sub-institutional branding depending on affiliation (College of Life Sciences branding) or c) self selection (“cool dude” branding) – these are in descending order of probability, ascending order of complexity (and narcissism).
    Personal spaces are any space that is restricted to just one user: spaces that index one of the following: 1) other spaces, 2) activity that takes place in other spaces, 3) spaceless activity that is meaningful to the user because of user’s relationship to that activity. Also any space where the user changes the dynamics of her relationship to the system: ie – changing one’s profile, notification options, etc.
  3. Shared spaces
    Any space that is not private to one user *and* needs branding by virtue of what the space functionally is. Can have 1) institutional branding, 2) affiliation (Life Sciences) branding, 3) cascading affiliation (Life Sciences > Entomology) branding; 4) space type specific branding [a) t&l, b) research, c) club, ad hoc]. There is a cascade involved in that branding closest to the root determines branding unless lower nodes specifically override parts or all of the branding elements. How the cascade works in practice is left to the institution’s best judgement and restraint – but the ability needs to be there, it is important to the sense of self of the institution and it’s subunits.

II) A skinning system needs to account for different functional locales

A given functionality has unique rendering needs that it takes care of itself. All non specific needs are taken care of by skinning system. Widget A is very unique and has unique needs, but the UI idioms it shares with the rest are shared (Save button is blue and flush left, for example)

III) A skinning system needs to be easy to customize

  1. enable and encourage customizations via a canonical mechanism, allow customizations via other means (but not facilitate them or even account for them, an institution should be aware of the risks involved)
  2. common locales and procedures to customize should be provided, named appropriately, with a clear and documented cascade.

V) A skinning system needs to hint at what elements can best be skinned and to what degree it is recommended they be skinned. The institution can do as it pleases – but probably would appreciate the help and guidance.

VI) A skinning system needs to account for special user needs

A user should be able to override any and all skin definitions because of low vision, poor eyesight, color blindness, other factors. This has two facets: the skinning system should not trump user stylesheets (if that is how the system has chosen to deal with this issue), or the skinning system needs to provide a set of alternates, and the user choice of the system alternate is part of the user’s preferences.

Advertisements

Skinning the Sakai 3 gateway

August 20, 2010

I took a long look at the Sakai 3 skinning architecture before the Denver conference and came to a set of conclusions. The most important conclusion was that this was not the time for conclusions, as the target was moving too fast.

Maybe now is the time to explore. As an experiment I pretended to be someone charged to change the gateway (and only the gateway). An effort was made to not even “think” about what would be the ideal process – but just to get the job done.

The results can be sen here and if that poor old tired seven year old Dell is down, in this screenshot

For the curious, the process is detailed below. The good news is that it took a about an hour (it shows!) and it would have taken less time if I actually knew how to use Photoshop and Illustrator. The bad news is that on reflection the path I took (out of ignorance or because it was the only path) was not optimal. More on this later.

dev/_css/sakai/sakai.index.css

Change watery background image to city scape

html {
  background: #093b52 url(../../_images/cityscape.jpg) top left repeat-x;
}

Hide header byline

.header-byline {
  display:none
}

Hide Sakai logo

.header-title img {
  display:none
}

Display an alternate banner via .header-title (adjusting width, height, padding and margins)

.header-title {
  color: #08415E;
  width:650px;
  font-size: 4.0em;
  float: left;
  margin: 25px 35px 25px 0;
  padding: 40px 0;
  background:url(../../_images/header-title-back.png) top left no-repeat
}

The “Register here” link is defined in this sheet as well, instead of in a global/core sheet

#register_here a {
  color: #000000;
  text-decoration: underline;
  font-weight: bold;
}

dev/index.html

The thumbnail is hardwired in the markup.

<img src="_images/panel_thumb.jpg" alt="__MSG__INSTANCE_NAME__" />

So either change the source, overwrite the image with a new one, or hide it and add a background to the container (.preview-box). Chose to change in the markup

<img src="_images/cityscape_panel_thumb.jpg" alt="__MSG__INSTANCE_NAME__" />

I also found I needed an additional canvas. For a zombie, sure, but it could have been a panel representing the institutional image of self, so added as a direct child of the body:

<div id="zombie"></div>

dev/_css/sakai/sakai.base.css

The background for all pages (other than index.html) is here

html {
  background: #75ADD7 url('../../_images/cityscape.jpg') top left repeat-x;
  font-family: Arial, Helvetica, sans-serif;
  line-height: 120%;
}

“Sign in” button of the gateway: like all buttons – depends on a sprite (retrieved from a common non-skinned context) applied and positioned in an outer and inner elements, changing the sprite may need a change of color of text.  The sprite is here:

dev/_images/button-sprite-5state.png

Changing the colors in the sprite might also entail changing the text color for the caption in the .s3d-button selector.

I left the buttons alone in this experiment.

footer files

Note: background of footer is a composite of inline CSS set in 1) devwidgets/footer/javascript/footer.js; 2) image background set in devwidgets/footer/css/footer.css and 3) background color in devwidgets/footer/css/footer.css

I left the footer alone in this experiment, except for the logo and links:

.sakai-footer .fixed-container img {
  display:none;
}
.sakai-footer .fixed-container a {
  color: #fff;
  text-decoration:underline;
}

The Sakai PDA portal

November 20, 2008

Sakai has a portal for small devices since 2.4. It is pretty bare bones but it does several neat things:

  1. it flattens the tool/site hierarchy so that they can coexist in the same breadcrumb
  2. it serves up an iframeless experience
  3. it elides many elements from the portal that would be noise in a small screen

Am working on several improvements to it for Sakai 2.7  under SAK-14827 and we are testing it at Michigan. It has been a very instructive experience constraining things to the small screen. What follows is a description of the changes, some tools and techniques that were useful, and some  observations from the preliminary testing.

The main tool turned out to be an iTouch that Chuck Severance donated to the lab. I tried several emulators such as iPhoney, Apple’s iPhone Simulator that comes with the iPhone SDK but there was no substitute for the actual thing.

Initially all I had in mind was polishing the portal, taking into account the screen size and the input device (your finger!). The PDA portal is served via a single Velocity template file present at a specific URL, so there was no need to do device detection – if you are there, you are using  a PDA (or, if you want to use a PDA you should use that URL). In the future it would be nice to route that  user agent to that URL automatically.

http://localhost:8080/portal/pda

The main complication was setting the viewport via the <meta /> tag. The official documentation is very telegraphic, but there is discussion about it. Eventually I settled on the following:

<meta name="viewport" content="width=device-width,
     user-scalable=yes,  initial-scale=1.0, maximum-scale=2.0"/>

The main issue here is font sizing after an portrait/landscape orientation change or after the user input zoom function takes place. Amazing to think that some people are using Javascript to detect the first.

The second task was to take all the styling references out of the template and out of the experimental portalstyles.css and create a CSS framework for the PDA. This entailed adding a pda.css + 3 images to each skin in the system, and querying in the template what was the skin in use per site.

Note: I have only checked into trunk the style sheets and images. The changes to the velocity template (pda.vm) and loginTool.java are being reviewed.

Now that the PDA portal was skinnable, it’s styles could be addressed via the CSS. The main preoccupations here were the following:

  1. font sizing
  2. adjusting padding/margins on links so that fingers of a moderate fatness could poke in the right place…
  3. curtailing horizontal spread

The results for the gateway pages and the site/tool pages are pretty good. Below with the University of Michigan skin, site navigation.

picture-3

The tool navigation:

picture-41

And an actual tool:

picture-1

I have craftily selected a tool for the screen-shot that works very well in this medium: the calendar summary from the excellent folks at Universidade Fernando Pessoa. Other tools are less fortunate.

A fun thing was adding icons for bookmarks. Following this tutorial I created a handful in no time. The iPhone actually takes care of all the glitz effects (corners, glassy look).

picture-5

And this is what the icon looks like in the “desktop”

picture-7

And what the Sakai skin looks like:

picture-8

Preliminary testing with the iTouch indicates some problem areas.

  1. Any tool that uses internal iframes is hosed.
  2. The browser detection identifies the iTouch as Safari, and serves it the default rich text editor, with it is unable to use – it should instead serve a plain text area.
  3. Cannot do attachments because the <input type=”file” /> is disabled in the iTouch.
  4. Not all tools render nicely, lots more to be done in this area.

RTL’g Sakai Tools

October 22, 2008

In order to create a skin for a RTL context we will be working in a the tool.css (so that we can override tool_base.css) of a new skin, named RTL. We will identify changes that need to be made, workarounds, failures to account for an RTL context in the tool design, etc.

If you are not very interested in the details  – the uncombed and disreputable skin is availiable here

If you want to know how we got to this and the shortcomings of this approach, read on.

We will begin with a simple tool view  – the Announcements list. What it looks like in a LTR context:

What the direction:rtl applied to .portletBody gets us. Am keeping the language as English.

Some nice things: the toolbar has been rearranged. The columns of the announcement table have been flipped correctly. Block elements are now flush right, such as the <h3>Announcements</h3>. The label of the view navigator select is not to the right of the select. The select itself is reoriented. The list paged lists, from right to left: “first page, previous page, next page, last page” correctly as the entire block has been flipped.

Some things that will need to be addressed: a) the pipes between the toolbar items look wacky and need to be aligned right; 2) the navigation panels need to be flipped ( a sad irony: if the layout of these and the toolbar  had been a table our work would be done); 3) the text direction of the cells inside the table needs to be adjusted.

The toolbar

Align the toolbar right. We will be working in the new rtl/tool.css):

.navIntraTool {
	text-align: right;
}

Add a border to the span child of the first list element:

}
/*special style for the first item, namely no border-left*/
.navIntraTool li.firstToolBarItem span{
	/*border:none;*/border-left:1px solid #ccc;
}

and take the border away from the last:

.navIntraTool li:last-child span{
	border:none
}

Since the design of the toolbar did not take into account a RTL possibility we had to resort to a pseudo class to identify the last element. We will see this problem elsewhere.

The navigation panels

The layout of these is set in tool_base.css. We will override in rtl/tool.css:

.viewNav{
	float: right;
}
.listNav{
	float: left;
}

The table list

/*skinned header of standard tab. data table*/
.listHier th, .listHier td{
	text-align: right !important;
}

The !important is needed to override the !important in tool_base.css – a bad decision that now needs to be dealt with.

The end result:

And in the target language:

Some issues remain with the navigation panels – reversing the floats did not exactly reverse the position, resulting in some inexplicable whitespace.  Someone help, please.

To recapitulate before we take on a more complex view of this tool: a) any series that identifies a first item also needs to identify the last; b) floats are not always totally reversible.

Forms and inputs

Some problems regarding the layout of the input, label and required marker troika. The orientation of the three is just not working due to floats. An example from create a new announcement.

So we rearrange the floats and display attributes, paddings, margins (if you are redoing an existing skin, look for some of these definitions elsewhere in the sheets if your results do not match):

.shorttext label{
	float:none;
	display:block;
	padding:0;
	margin:0;
}
.shorttext .reqStar{
	float:right;
	margin-right:-7px;
}
.longtext label{
	float:none;
	display:block
}
.longtext label .reqStar{
	float:right;
	margin-right:-7px;
}

So:

And in Arabic:

The other input types render correctly without any tweaking (this is also from create a new announcement):

While on the subject of inputs, the following is also needed if there is to be mixed RTL and LTR content:

input, textarea{
	unicode-bidi: override;
}
This opens an  additional level of embedding and overrides the Unicode character ordering, reordering the sequence to the value of the direction property. 

A quick glance over the core tools and it seems most rendering now is OK. There will be exceptions where the developer has been forced to apply sui generis layout or styles because of the paucity of the default styles. There will also need to be addressed – please leave some comments where that is the case, thanks!

Off hand – here are some locales that need more work because of these and other reasons:

  1. Filtering controls in Schedule list view.
  2. “Add” menu in Resources – text is misaligned.
  3. Certain icons are facing in the wrong direction – such as disclosure triangles. These will need to be replaced in the file system when they are inline images, or in the skin when pulled as background images.
  4. The FCK Editor – needs configuration – information on configuring the FCK Editor for RTL is here. There are language files for Arabic and Hebrew, Persian as well. Probably a lot of other stuff that a native speaker could figure out needs to be tweaked.
  5. Placement of icons inside certain blocks needs to be tweaked – see alertMessage etc. 

The uncombed and disreputable skin is avaliable here.


RTL’ng Sakai from portal to tools

October 20, 2008

Some things we left disheveled in a previous post about the RTL Sakai Portal, I will address these below. We are modifying a pre-existing portal in case this is useful to a context where the LTR and the RTL experiences need to coexist – then you can just modify the existing LTR portal skin. If the context is strictly RTL, you might be better off starting from scratch. I will provide a starter RTL skin at the end.

Site navigation

Some portal clean up: the pipes between site links still reflect a LTR orientation.

Change the location of the borders:

/*links to other sites*/
#siteLinkList a,#siteLinkList a:link,#siteLinkList a:visited{
    color: #fff;
    padding: 2px 6px 2px 4px;
    text-decoration: none;
    /*border-right: 1px solid #fff;*/border-left: 1px solid #fff;
}

and take borders away from the last link (which is the left-most one):

#siteLinkList li:last-child a{
    border:none
}



Portlet titles

The portlet titles also need sorting, flip the floats and text directions :

.portletTitle .title{
	/*float: left;*/float: right;
}
.portletTitle .title a{
	/*float:left;*/float:right;
}
.portletTitle .action{
	/*text-align: right;*/text-align: left;
}

So now the direction is correct:

Presence

Presence also shows the old LRT orientation:

On the portal level – adjust the title:

#presenceTitle{
   font-size: .7em;
   /*text-align: left;*/text-align: right;
   margin-left: .5em;
}

The presence list is inside of an iframe – and as such it is a tool, so it will be a useful segue to RTL’ng the tools. As with the portal we are adding the direction attribute to the first child of body (.portletBody).

.portletBody{
   direction:rtl
}

This will get us a lot of LTR > RTL changes for free in all of the tool descendants as we will see later. Except in the presence list as that doc does not have a .portalBody wrapper!!! Since presence does not have a .portletBody we need to add direction attribute to the list itself and fiddle with the paddings:

/*below for "presence in chat" functionality*/
.presenceList{
   font-size: .8em;
   list-style: none;
   margin: 0;
   direction:rtl;
   text-align:right;
   /*padding-left: .1em*/padding-right: .1em;
}

.presenceList li {
    /*padding: 0 0 0 .7em;*/padding: 0 .7em 0 0;
    margin-bottom: .2em;
}

Looks better now:

The results this far:

Next post – the tools in all their glory.


RTL Sakai

October 10, 2008

Back in Sakai 2.0 I went through an attempt to serve up a Right To Left language Sakai experience. At the time this was just an academic exercise, as there were no language resource bundles for Arabic, Hebrew, Farsi, etc. I just wanted to torture test the framework, frankly. It was amazingly simple to modify the portal framework via the skin to serve up an adequate portal. The tools were a different matter altogether, being so varied, and represented a number of challenges.

Now there is a Arabic translation (in trunk), so I thought I would go through the process again and hope it is useful. The framework has changed substantially also, so it was due. In this post I will outline the steps to turn a LTR portal (the Michigan CTools) into a RTL portal for some hypothetical university where Arabic is the main language. Disclaimer: I took Arabic in college, but it is long forgotten – so I am relying on random boilerplate and on iGoogle’s translator service for example strings. Don’t read too much into it!

In a future post I will go through one or two tools in a similar fashion.

  1. Use trunk. Add ‘ar’ to the locales attribute in sakai.properties, start tomcat.
  2. Login as admin. Create a user, give him a RTL name. In this case I used داود سيلڤَر (with a Latin id if you are not a RTL speaker, I used daud).
  3. We will want داود to mess around with tools as ‘mantain’ to get the full experience so create a site and add him as mantain. I used boilerplate Arabic for site title and description.
  4. Login as ‘daud’
  5. Change your Preferences > Locales to ‘Arabic’
Tada! First impressions – neat! Second impression – I cannot read it, it is too small. We will address that later.

First thing – let’s add a direction attribute to first child of the portal body:

#portalOuterContainer{
	direction: rtl;
}

This gets us started. All HTML elements that inherit this attribute and use it will reverse direction. Now we need to address the elements that are not affected.

Some things will need to be addressed substantially: 1) the orientation of the mast head needs to be fixed so that from RTL: logo, banner, login; 2) site list orientation; 3) the portlet title (Announcements) also needs to be reconfigured as well; 4) finally – the portal content needs to be from RTL: tool links, content.

Reorienting the mast head

We have this mess to contend with:

I have outlined the three components in red. From LTR: #mastLogo, #mastBanner, #mastLogin. They are all floated. We need to reverse the order, so let’s reverse the float:

#mastLogin{
  /*float:right*/ float:left
}
#mastBanner{
  /*float:left*/float:right
}

That is it – really. Am omitting all of the other attributes. Which gives us:

The order of labels and inputs is following the direction attribute of the body. Everything else needs work. Am going to hide #mastLogo because we do not need it. Any graphic element can be poked in as a background of any of the (embarrassingly numerous) other canvases available. I will also add different logos and background colors.

So – new image for banner_inst.gif and reverse the padding orientation on #mastLogin:

#mastLogin{
	float: left;
	text-align: right;
	/*padding-right: 15px;*/padding-left: 15px;
	vertical-align: top;
}

Which leaves us with:

The language bundle seems to be missing the Arabic equivalents for the input labels, but the position basics are in place: logo to the right, login to the left.

Reorienting the site navigation

We are left with:

Swapping the floats (links and select) reflect the importance of the 2 in the RTL context:

#linkNav{
	/*float:right*/ float:left
}
#selectNav{
	/*float:left;*/ float:right
}
So (am hiding the banner_inst.gif image):

Although the the direction:rtl in the body gets us the RTL select, it does not flip the orientation of the inline list that the site links are, a list is a list and has an order. We will need to be more devious…

#siteLinkList li{
	display: inline;
	float:right;
}
Yay – the order of importance reflected in the original LTR is now reflected in the RTL context: My Workspace, sites, other sites. Some minor touches are still needed such as the separators between site links, padding, etc.

Reorienting the content

The site content consists of a container (imaginatively id’d as #container), with two children: #toolMenuWrap (the tool link upper parent) and #content. Again , we have to tinker with the float of one:
#toolMenuWrap {
     border-right:2px solid #FFFFFF;
     color:#000000;
     /*float:left;*/ float:right
     padding:0 0.5em 0 0;
     text-align:right;
     width:9.6em;
}

and the margin of the other

#content{
	padding: 0;
	margin-top: .5em;
	/*margin-left: 11em;*/ margin-right: 11em;
}

and the text-align of the #toolMenu list items:

#toolMenu li{
	margin: 0;
	width: auto;
	padding: 0;
	border: 1px solid #fff;
	/*text-align: left;*/text-align: right;
}

Not bad, although quite a bit of clean up left to do (the presence block, the portlet titles (which are in the portal doc of all things) for example, the footers, etc.) And being ignorant of the actual use and needs, quite a few things I have overlooked as well – do leave comments setting me straight. I will upload the finished skin later. I will also address soon the skinning of the tools (gulp).


Print previews on the cheap

August 22, 2008

1. Put this in the document (as well as a link to the jquery file).

<script type="text/javascript">
  $(document).ready(function(){
    setupLinks();
    setupPrintPreview();
  });
</script>

2. Put this in your external javascript:

function setupLinks(){
  $('a.print-window').click(function(){
     var w = window.open(this.href, 'printwindow', 'width=600,
          height=400,scrollbars=yes,resizable=yes');
     w.focus();
     return false;
  });
}

3. And this

function setupPrintPreview(){
  if (window.name == 'printwindow') {
   // all the settings below would need to be edited
    $('.portletBody *').css({
        color: '#000'
    });
    $('.bookList').show();
    $('.collapse').show();
    $('.expand').hide();
    $('.noPrint').hide();
    $('.portletBody').css({
        padding: '1em',
        fontSize: '.85em'
    });
    // provide a print link
    $("h3").append('a link with an
        'javascript:window.print()' href value);
  }
}

In (1) we are calling a function (2) that bind the onclick event to any link with a class of ‘print-window’ – opening the current document in a named window. In (3) – if a window matches the given name, then massage the elements for the print medium, hide elements that were classed as ‘noPrint’ (formish things, whatever), and add a link with an ‘javascript:window.print()’ href value to the DOM.

The end. Lots of room for improvement, of course – the massaging would be done best by swapping the stylesheets, for example.