Lars Nielsen's Discoveries

April 20, 2012

Inconsistent colour rendering in the web browser with PNG images

Filed under: Branding,SharePoint — Lars Nielsen @ 7:58 pm
Tags: , ,

When you need to add images to the branding on a site, you (or whoever creates the image) need to decide what format to use for the image files; this basically comes down to a choice between GIF, JPG or PNG. This article is a good discussion of which one to use.

The general advice is to use JPG for photos and PNG for everything else. You only need to restore to GIF if you need to work with older browsers (for example if you want transparency on IE6) although there is the PNG fix for IE6 that can help to get round this.

But recently I was working with an image for a web button that had to match the hex RGB colour (e.g. #cccc99) of a DIV background that was set in CSS. I started out asking the graphic design people for a PNG file, as this is a more suitable lossless form for graphic images like this. I checked the PNG file with a colour picker to make sure that it had the right hex RGB colour.  Then, I put the image tag into the page HTML and had a look at the page in the browser.  The colour of the PNG image had changed. I checked with the colour picker in the IE Developer Toolbar and it wasn’t the same RGB value as the original PNG file.  Visually it was close, but not quite the same. In other words the browser had rendered the colour within the image to something slightly different from what was in the original PNG file.

This is all down to Gamma Correction and the way that different browsers implement it.   You can use this page to test different browsers and how they correct PNG colours (even when you don’t have gamma correction information in the source PNG file).  For example, look at this page in both Chrome and IE 9 – see how different they are.  It certainly makes life difficult when you’re trying to match the RGB colours exactly if browsers decide to change them!  In theory you can turn this off within the PNG file but some browser don’t respect that and many graphics applications like Paint.NET don’t allow you to turn it off anyway when you save to PNG.

In the end it proved so difficult to deal with that I went for JPG format instead!  If anyone has any better solutions please let me know.

Advertisements

February 29, 2012

White boxes: handling special ANSI characters in XSL and XML

Filed under: Branding,SharePoint — Lars Nielsen @ 9:43 pm
Tags: , ,

Using a data view web part you can render XML content from a public XML feed (a vacancies list) onto a SharePoint page. You add the URL of the data feed into the XML files section of the data source library.  The XML feed I was using was simply a public URL which returns pure and properly formed XML content.  The XML content that comes back starts with this:


<?xml version="1.0" encoding="ISO-8859-1"?>

This says that the XML is (or should be) encoded using ISO-8859-1.  I wrote my XSL file and configured the dataview web part to reference the XSL.  Everything worked fine except that the text on the web page contained small white boxes in place of some of the punctuation marks. On inspecting the raw XML from the feed, I found that there were characters in the byte stream that correspond to the Windows 1252 code page an which are not part of the ISO-8859-1 standard. The problem I had particularly was with character #92 (hex) which is a bacwards-facing apostrophe commonly inserted into text by Microsoft Word as a “smart quote”. I suspect that someone copied the text originally directly out of an MS Word document and pasted into a textbox, so that the character ended up in the database, and rendered out into the XML.

I wanted my output from my XSL transformation to render as UTF-8 which is the encoding used by the containing SharePoint page. So I tried setting my XSL to encode the output by adding an xsl:output line.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>

I thought this might render the backwards apostrophe as a readable UTF-8 apostrophe, but it didn’t. So I tried switching the encoding to Windows-1252:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="windows-1252"/>

This rendered the backwards apostrophe correctly on the screen (in IE 8) but broke other characters instead. I realised the problem was the original XML should not be using that #92 character but instead should use a regular single quote character (#27 hex) which is what the HTML character entity “&apos;” translates to.  So in my XSL I added a template to replace character #92 with #27.  To represent these characters in XSL or XML you can use ampersand – hash followed by the decimal (not hex) code for the character followed by a semicolon. #92 hex is 146 decimal, and #27 hex is 39 decimal. So I created an XSL template and called the template by passing in the original string as a parameter, like this:

<p class="description">
   <xsl:call-template name="CleanUpUnreadableChars">
   <xsl:with-param name="str" select="job_description" />
   </xsl:call-template>
</p>

.....

<xsl:template name="CleanUpUnreadableChars">
   <xsl:param name="str" />
   <!-- Replace ANSI char 146 (backwards apostrophe) with char 39 (single quote) so that it renders as a readable char -->
   <xsl:value-of select='translate($str,"&#146;","&#039;")' />
</xsl:template>

This works OK and transforms the “unprintable” backwards apostrophe into a standard single quote that renders on the browser as expected. Using the XSL translate function I can add other characater transformations later as necessary if I find other spurious characters in the XML feed.

May 26, 2011

Equal height columns using div and CSS

Filed under: Branding,Good Practice,SharePoint — Lars Nielsen @ 7:59 pm
Tags: ,

Finally now SharePoint is using DIV elements in the v4.master page, rather than using tables for layout as SharePoint 2007 did (and which is not xhtml compatible and has a load of other problems as well).

Using DIV’s rather than tables for layout is a great idea, but some things become more difficult to do with CSS and DIV’s. One of the more common issue is now to get a screen layout with two columns of equal height.  With tables in HTML it was easy – just create two cells in a row and they will be sized to be the same height by the browser.  DIV’s however are given a height dynamically to contain their content so it becomes quite difficult to create even a simple layout with 2 columns (DIV’s) of the same height.

There are plenty of possible  solutions to this, and this post lists some of them.  In my work recently I was working on some CSS that seemed to be following this technique.  I guess it works, but it’s not exactly straightforward, and I was having trouble getting it stripped down to just two columns and working in a fixed width design rather than flexible width.  So in the end I found this simpler alternative and used that as the basis for my CSS.  It works fine in all the main browsers (although there is a problem with IE 6 and 7 – see below) and doesn’t involve the complexity of defining widths and relative positions in several places.  It uses a similar trick, in making the background of the whole wrapper to be whatever you want for the background of the left hand column, and the other columns sit to the right and cover the background with another background.  In this, I managed to create a layout with 2 columns of equal height with quite simple and basic CSS.

Here’s the code for a page to show the technique:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>div test</title>
<style type="text/css">
div.Main {
  width:980px;
  background:red;
  color:white;
  border:none;
  margin:0 auto;
}

div.Left {
   width:165px;
   float:left;
}

div.Middle_Right {
   margin-left:165px;
   border-left:none;
}

div.Right {
   margin-left:0px;
   background:blue;
   border:none;
}

div.Clear {
   clear:both;
}
</style>
</head>
<body>
<div class="Main">
    <!-- Left -->
    <div class="Left">
    	<div id="New div">
    	Left<br />Left<br />Left<br />Left<br />Left<br />Left<br />Left<br />Left<br />
    	Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left Left
 		</div>
    </div> <!-- /Left -->
    <!-- Middle + Right -->
    <div class="Middle_Right">
        <!-- Right -->
        <div class="Right">
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
		Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right Right
	        <div class="Clear">
	        </div>
        </div> <!-- /Right -->
    </div> <!-- /Middle + Right -->
</div> <!-- /Main -->
</body>
</html>

Update

This technique seems to cause problems with IE6 and IE7 in that the colour of the left hand DIV bleeds over into the right hand div at the bottom if the left hand div is higher than the right hand one, and you resize the browser to be less high than the DIV’s themselves. Other browsers seem to be OK. In the case of SharePoint 2010, it doesn’t officially support IE 6 anyway, and nearly everyone who uses IE 7 has upgraded to IE 8 at least, so in practice this may not be too much of a limitation.

May 6, 2011

My Links loses the orange gradient background on hover – A CSS case-sensitivity issue

Filed under: Branding,SharePoint — Lars Nielsen @ 7:39 pm
Tags: ,

In trying to create CSS to style a custom master page in SharePoint, I discovered a strange quirk (you’ll see the significance of that word later) in the way SharePoint out-of-the-box styles and controls work.

The “My Links” link at the top of the page next to the “Welcome” box is rendered by the following line in a master page:

<SharePoint:DelegateControl runat="server" ControlId="GlobalSiteLink2" Scope="Farm"/>

If you look at the HTML that comes out on the page, it’s marked up with HTML like this:

<TD class="ms-globallinks">
  <SPAN id="ctl00_ctl16_MyLinksMenu">
    <SPAN style="DISPLAY: none">
      <MENU id="ctl00_ctl16_MyLinksMenuMenuTemplate" type="ServerMenu" largeIconMode="true"></MENU>
    </SPAN>
    <SPAN title="Open Menu">
        <span id="ctl00_ctl16_MyLinksMenuMenu_t" class="ms-SPLink ms-hovercellinactive" onmouseover="MMU_PopMenuIfShowing(this);MMU_EcbTableMouseOverOut(this, true)" onclick="javascript:FetchCallbackMenuItems('ctl00_ctl16_MyLinksMenuMenuTemplate'); MMU_Open(byid('ctl00_ctl16_MyLinksMenuMenuTemplate'), MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu'),event,true, null, 0);" nowrap="nowrap" foa="MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu')" hoverInactive="ms-SPLink ms-hovercellinactive" hoverActive="ms-SPLink ms-hovercellactive">
          <a style="white-space: nowrap; cursor: hand;" onkeydown="MMU_EcbLinkOnKeyDown('ctl00_ctl16_MyLinksMenuMenuTemplate'), MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu'), event);" id='ctl00_ctl16_MyLinksMenuMenu' oncontextmenu="this.click(); return false;" onfocus="MMU_EcbLinkOnFocusBlur(byid('ctl00_ctl16_MyLinksMenuMenuTemplate'), this, true);" onclick="javascript:return false;" href="#" serverclientid="ctl00_ctl16_MyLinksMenuMenu" menuTokenValues="MENUCLIENTID=ctl00_ctl16_MyLinksMenuMenu,TEMPLATECLIENTID=ctl00_ctl16_MyLinksMenuMenuTemplate">
            My Links
            <IMG border=0 alt="Use SHIFT+ENTER to open the menu (new window)." src="/_layouts/images/blank.gif">
          </A>
          <IMG alt="" align="absBottom" src="/_layouts/images/menudark.gif">
        </SPAN>
    </SPAN>
  </SPAN>
</TD>

I’m sure your first thought on seeing this is: yuck! It’s the familiar wonky SharePoint HTML, but I want to point out this class assignment in the inner <SPAN> tag:

class=”ms-SPLink ms-hovercellinactive”

and this attribute:

hoverActive=”ms-SPLink ms-hovercellactive”

What happens here is that as the user runs the mouse over “My Links” the onmouseover attribute calls the Javascript function MMU_PopMenuIfShowing. That reads the hoverActive attribute and then dynamically changes the CSS class for the SPAN tag from “ms-SPLink ms-hovercellinactive” to “ms-SPLink ms-hovercellactive”, and that’s what creates the orange gradient background on “My Links” when you hover over it. Now if we look in the out-of-the-box core.css file, which is always on every SharePoint page, it has a CSS definitions for classes ms-hovercellinactive and ms-hovercellactive – here’s the extract from core.css:

.ms-HoverCellInActive,.ms-SpLinkButtonInActive
{
border:none;
margin:1px;
color:#4c4c4c;
vertical-align:top;
background-color:transparent;
}
.ms-HoverCellActive,.ms-SpLinkButtonActive
{
border:#6f9dd9 1px solid;
vertical-align:top;
background-color:#ffbb47;
background-image:url("/_layouts/images/menubuttonhover.gif");
}

So core.css defines the class as “ms-HoverCellActive” but in the HTML SPAN tag the class attribute is “ms-hovercellactive”. Does it matter that they have different case? Well, yes and no. Normally the SharePoint default.master page has no DOCTYPE definition at the top. This puts IE (8, not sure about 9) into Quirks Mode, and in Quirks Mode it ignores the case of CSS classes so it will render correctly. However, best practice in web design is to include a DOCTYPE and to take IE out of Quirks Mode. In my master page I’m using:

<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

As soon as you put a DOCTYPE at the start of the page, and take IE out of Quirks mode, it starts to treat CSS class names as case-sensitive and expects the case to match. When you hover over “My Links” you lose the orange gradient background. To fix this, you need to define CSS for ms-hovercellactive and ms-hovercellinactive explicitly, in your own custom CSS file.  You can either replicate what’s in core.css, or define your own CSS for these classes.

July 30, 2010

Custom Application master page: traps and workarounds

Filed under: Branding,SharePoint — Lars Nielsen @ 8:48 pm
Tags: , , ,

I’ve been having some fun trying to change the master page for some of the application pages in the _layouts folder in SharePoint.  I’ve created a special HttpModule that applies my custom master page to some of the pages – just the ones that are normally seen by people who have member level (contribute) permission on a team site.  Most of the application pages are only visible to people with higher level permission than contribute, but a few pages (for example, setting up a new alert, or uploading a file) are visible to members. In my case the client wanted those pages to be branded to look like the rest of the site, not the standard blue-and-orange SharePoint branding that you get with application.master. I managed to apply the standard site master page to a couple of the application pages (the ones for uploading documents and for setting an alert) with no problems.  But as I began to apply it other pages in the _layouts folder, I started getting errors about missing placeholders, or Javascript null reference errors.   The missing placeholder errors are OK to fix – it’s just a question of finding the placeholder in the application.master file and adding it to the custom master page.  I follow Heather Solomon’s advice and have an invisible panel at the bottom of the page, and all the placeholders go in there (unless they need to be visible like PlaceHolderLeftActions – see later). The fun starts when you start getting other kinds of errors which don’t tell you what the real problem is.  All you have to go on is the HTML that comes down to the browser.  Using IE 8 you have a pretty good developer toolbar, which helps to track down what exactly has gone wrong.  But that only takes you part of the way; you still have to work out what’s actually wrong on the master page itself.  That can take a lot of guesswork and trial and error, trying to work out which SharePoint or ASP.NET controls are the source of the problem.

The Design Console

The standard design console in SharePoint is the one that appears when you edit a page without the publishing features activated (.e.g. in a regular team site)

In the standard master page this is generated by the DesignModeConsole control in the WSSDesignConsole placeholder, like this:

ContentPlaceHolder ID="WSSDesignConsole" runat="server">
       <wssuc:DesignModeConsole id="IdDesignModeConsole" runat="server"/>
ContentPlaceHolder>

I added this code into my master page but strangely the design console bar refused to show up on the page when I edited it. Eventually, by looking at the HTML source of the page when it was being edited, and working backwards from the master page, I figured out that the HTML rendered by this control starts with a <TR> tag.  This means it won’t work unless it’s sitting inside an HTML table.   Well of course using tables for layout is bad practice (although it’s something you find all over the place in SharePoint pages) so I had stripped out as much of the table-based layout as I could from the my master page.  As  a result, my placeholder was not inside a table and the design bar refused to render in the browser.

The fix was to embed the placeholder inside an HTML table like this:

<table width="100%">
       <tbody>
             <asp:ContentPlaceHolder ID="WSSDesignConsole" runat="server">
                    <wssuc:DesignModeConsole id="IdDesignModeConsole" runat="server"/>
             </asp:ContentPlaceHolder>
        </tbody>
</table>

Picture Library thumbnails and film strip views

With my custom master page, when I looked at a picture library, the thumbnails didn’t show up by default, and the filmstrip views just did nothing.  Only details view was showing. After some research, some reverse engineering on the HTML for the Picture Library views, and some trial and error, I found this was because I had to put in a PlaceHolderLeftActions control in the master page, and it has to be before PlaceHolderMain.  The PlaceHolderLeftActions control adds some essential Javascript in the page which the dropdown relies on.

Create View or Modify View pages Javascript breaks

When I created a new view or modified an existing view, the ViewNew.aspx or ViewEdit.aspx pages both displayed OK but the clickable plus sign icons next to “Group By”, “Total”, “Styles” etc. were missing, and the panels underneath them (which are normally hidden until you click the plus sign) were all visible.  I eventually found a clue in the documentation about SearchBoxEx that the problem is caused by a second copy of the ShowHideGroup Javascript function on the page when you have a search box on the master page.  To make things more difficult, this second copy is in Search.js so it’s not even listed in the source HTML of the page –  hard to track down!

To fix this, I took the Javascript of the ShowHideGroup function from the Search.js file and and put it in a <script> tag on the bottom of the master page.  This becomes the third definition of the function on the page, and overrides the second definition of the function from the search box.

Datasheet View locks up the browser

Another problem happened when I switched from standard view to datasheet view in a list.  Doing this caused the browser tab to lock up until I closed down the tab.  Fortunately this one wasn’t quite so bad because there were clues here and here; SharePoint does some fancy scripting to resize the element dynamically, but this doesn’t work once you move the navigation controls around.  I adapted the Javascript code to cope with the fixed-width div that I was using for the main content placeholder.

Scroll Bars and Overflow

If you have a fixed-width page design you might need to make use the CSS Overflow attribute to cope with cases where the main content gets really wide.  This could happen for example if you create a view of a list with a load of columns that can’t be wrapped around.  Here’s an example where the navigation has been moved from left to right, and when you view a document library with a lot of columns it runs over into the right hand navigation at the Content Type column:

Without overflow the view runs into the navigation

To get around this you can use the CSS Overflow attribute to force a horizontal scrollbar on the div that’s too wide, so it looks like this:

Overflow with IE7

Well this is better because at least you can scroll the view horizontally to see the missing columns.  But the field headers are not overflowing properly, and there’s a spurious vertical scrollbar on the right hand side as well.  This is a peculiarity of IE and the way its vertical scrollbar works.  That’s how the view displays in IE7, or in IE8 when the page is set to IE7 mode.  Switch the browser to pure IE8 mode and it looks much better:

Overflow In IE8

To get the master page to force IE 8 to use IE 8 standards when rendering the page, change this meta tag in the <head> of the master page like this:

<meta http-equiv="X-UA-Compatible" content="IE=8">

Can’t delete the master page

When you try to delete the custom master page from the master page gallery, you get an error:

This item cannot be deleted because it is still referenced by other pages

Microsoft says to work around this by hiding the master page but that’s not ideal.  Katrien De Grave has a better solution by copying the master page to a temporary folder and then deleting the folder.

Blog at WordPress.com.