Showing posts with label Customization. Show all posts
Showing posts with label Customization. Show all posts

11 May 2010

Inserting Arbitrary Links in a SharePoint Calendar

Some time ago a client hired us to build a custom web part that, among other things, would color code events based on a category assigned to an event, embed an “information” link into each date of a 30 day calendar view and provide a printable view for a specific month.  At the time, SharePoint 2007 was relatively new, as an organization Consejo had been building custom extensions for SharePoint 2003 for some time and it just made sense to continue down the path of a custom web part.  Interestingly, the task of build a custom calendar web part that would properly display events in an event list is harder than you might think (another story).

First, I would always recommend trying to buy before building; as a developer it’s tempting to build, but usually less expensive long-term to buy.  And, while there were at least one or two commercial web part options that provided color coding (Bamboo’s calendar plus web part was something we seriously considered), nothing gave our client the ability to embed their information link.  The goal for this link was to create a “light” integration between the SharePoint event calendar (where they posted all of their corporate events) and a 3rd party application that would display information related to catering for that date.  Essentially, when you clicked the information link, a new browser window opened to the URL of the event application with the date associated with the specific icon the user clicked.  Pretty simple and easy.

After a far-too-long development cycle to complete, the web part has been generally working within that client’s environment for some time.  However, they recently approached us for an update.  The request kicked off another round of investigation and an epiphany of sorts.

While attending SharePoint Summit 2010 in Montreal, I had the good fortune of attending Mark Miller’s (End User SharePoint) session on enhancing the SharePoint interface through jQuery.  Coincidentally enough, very little of Mark’s talk was about jQuery specifically, though he did share a few examples.  What he did show were numerous ways that you could manipulate the standard SharePoint interface using other JavaScript bits, including color coding a calendar, creating a printable interface and creating a tabbed interface.  Many of these scripts were developed by Christophe Humbert from Path to SharePoint.

After attending the session, trying the color coding script myself (really a combination of a calculated column and JavaScript) and seeing the possibilities, I decided to try my hand at recreating the custom web part we developed using just JavaScript and calculated columns.  While Christophe’s approach helped with the print view and the color coding, he didn’t have an example for the information link.  Fortunately, a little experimenting on my part produced the script shown below.

<script type="text/javascript">
/*
Insert the event icon script
Written by Consejo, Inc.
Questions: info@consejoinc.com
*/

var iterator = document.getElementsByTagName("td");
try
{
var i = 0;
var thisNode;
while (i<=iterator.length - 1 && iterator.length > 0)
{
thisNode = iterator[i];
var moreNodes = thisNode.getElementsByTagName("div")
if(moreNodes != null && moreNodes.length > 0)
{
for( var x = 0; x < thisNode.attributes.length; x++ )
{
if( thisNode.attributes[x].nodeName.toLowerCase() == 'class' && (thisNode.attributes[x].nodeValue.toLowerCase() =='ms-cal-topday' || thisNode.attributes[x].nodeValue.toLowerCase() =='ms-cal-topday-today'))
{
try
{
var onClickEvent = thisNode.getAttributeNode('onclick').nodeValue;
var origEventDate = onClickEvent.substring(16,37);
var cleanUp = new RegExp(/^([1-9]|1[012])+\\u002f+([1-9]|[12][0-9]|3[01])+\\u002f+\d\d\d\d/);
var cleanEventDate = cleanUp.exec(origEventDate)[0];
cleanEventDate = cleanEventDate.replace(/\\u002f/g,"-");

moreNodes[0].innerHTML += "<a href=\"http://www.videodetective.com/dvdcalendar.aspx?week=\"" + cleanEventDate + " style=\"font-size:8px;position:relative;right:-45%;\">Event Info</a>";
}
catch(err){}
}

}
}
i++;
}
}
catch (e)
{
alert( 'Error: ' + e );
}



 


To implement this script, simply copy and paste this JavaScript into a Content Editor Web Part loaded after the calendar view web part.  If you want to enhance the link, simply insert an IMG tag where the text is shown. 


The link in the script is to a site that shows what DVDs were released on the date extracted from the SharePoint calendar’s onClick event; a little regular expression work helps to extract the value provided by SharePoint.    Obviously, you should change the URL in the script to something that meets your needs, unless you really want to know what DVDs are to be released.



I very much want to thank both Mark and Christophe for demonstrating a very light-weight approach to adding new functionality to the SharePoint interface.  Next time, I’ll think twice about writing mountains of C# when trying to achieve a client’s goals.

17 January 2009

Customizing a SharePoint Site's Visual Design

One of the common questions we get from clients is "how do I apply a custom design to my SharePoint site?"  While SharePoint's interface is relatively clean, it has the ubiquitous "SharePoint Look."  Most clients want to make their sites match their brand, palette and navigational style.  However, it's not always easy to figure out the various elements that need to change.

To that end, here's a short list of options for changing SharePoint's look into something more complimentary to your brand:

  1. Custom SharePoint Theme
    A Theme, in SharePoint terms, is like a fresh coat of paint over the existing SharePoint interface.  A Theme is driven exclusively by a series of CSS files located on the file system (in the "12 Hive").  The best custom themes simply override styles that can be found in the various CSS files that accompany the SharePoint software, like CORE.CSS.  The advantage to a custom Theme is that it takes very little to create some dramatically different interface styles; since so much of SharePoint's interface is CSS drive (to its credit), you can do quite a lot by simply changing the theme.  The easiest way to create your own theme is to copy an existing one (located in X:\program files\common files\microsoft shared\web server extensions\12\template\themes where X is your SharePoint installation drive).  Once you've copied the directory, renamed it, updated the included CSS and added your images, just modify the THEMES.INF to point to your new custom theme.  If you'd like detailed instructions, take a look at this MSDN article.

    image
    Figure 1 - List of Themes included with SharePoint
  2. Custom Master Page(s)
    In the .NET v2.0 timeframe, Microsoft introduced a concept called a "master page."  A Master Page, in SharePoint vernacular, represents all of the common elements of pages that share that Master Page.  Using an overloaded term, "template" might best describe at least part of the concept.  While Master Pages don't represent that entirety of the visual design, they establish the major elements and then determine where variable elements of a page can be placed.  By using "container objects," called placeholders (another overloaded term), Master Pages can establish the interface framework without interfering in a specific implementation.  Using various Master Pages with the same Page Layout (more on that shortly), you can produce vastly different looking sites.  In fact, SharePoint (MOSS) comes pre-loaded with several master page examples (mostly with names including "band" in them).   If you currently have a publishing enabled MOSS site (collaboration portal, News site or Publishing portal are the standard ones that enable this feature by default), you can change your master page in Site Settings.  There you'll have the option of choosing between various pre-installed Master Pages for both the Site Master Page and the System Master page.  In addition, you can create your own custom Master Page to introduce a radically different look.   If you are using WSS or don't have the publishing feature enabled, you can still use different Master Pages.  However, you'll either have to write a small utility to change the Master Page or you can download an open source extension to SharePoint from CodePlex to assist you in changing your master page (among other visual design elements).  Microsoft published a short article on customizing master pages on their MSDN site.  Remember though, you can have many Master Pages defined in your SharePoint site collection, but you can only use one Master Page per SharePoint site (unlike a traditional ASP.NET application).
    image
    Figure 2 - Option in Site Settings for changing Master Page
  3. Creating Custom Page Layouts
    Page Layouts, like Master Pages, were released as a part of the .NET v2.0 framework.  They are used in conjunction with Master Pages to create the overall visual design of a SharePoint site.  Page Layouts define what content will be placed into placeholders defined by the Master Page.  SharePoint ships with a number of different layouts.  By default, selectable Page Layouts are only available when using a publishing enabled site; you can choose a specific Page Layout for other SharePoint-types.  However, if you are using a publishing-enabled site, you can further refine your SharePoint site's look by leveraging customized Page Layouts.  Just keep in mind that Master Pages and Page Layouts are pretty tied together; if you create a Page Layout that uses placeholders from a customized Master Page, that Page Layout may not be "compatible" with out-of-the-box layouts.  For more information on creating Page Layouts, see this MS Office article.

In many cases, organizations will need to leverage more than one of these techniques to create the look they desire.    The specific technique will largely depend on how different you want your SharePoint site to look.

Once you've completed your changes, the best way to "install" the new, customized look, is through a SharePoint Feature.  A feature can provision all of the files involved in the customizations and programmatically enable them on one or more sites within the site collection.  The advantage to this approach is that by activating or deactivating the feature, the customized look can be enabled or disabled without vastly affecting the function of the site; this approach is also the way Microsoft recommends making changes to your SharePoint site.

Now, if all of this is too much to take in, or if you just need some help, Consejo has recently created a new SharePoint Branding Fast Track offering.  This offering is meant to help organizations quickly develop a customized the look and feel for their SharePoint site.   In a short 11 business days, we create a semi-custom visual design for your site, leveraging our pre-build master pages, page layouts and themes.  For more information or to discuss your needs, contact our sales group.

03 July 2008

SharePoint and Oracle Internet Directory (LDAP)

[UPDATE 6 SEPT 2010] The code has been posted on a new article about connecting SharePoint to Oracle LDAP

I have a client who recently wanted to leverage their Oracle Internet Directory server to authenticate users in SharePoint.  Since OID is LDAP compliant, I figured I could just use the generic LDAP provider with SharePoint.  Turns out, that provider is only supplied with MOSS and my client was using WSS.  So, off to Visual Studio to create a custom membership provider I went. 

I've seen a number of posts regarding the creation of custom membership providers for non-Microsoft directory sources like SunOne and OID.  However, I never saw any code samples (most folks didn't seem to be able to get it to work).  While other posts on custom membership providers tended to rehash the same material on SQL Membership.  As it turns out, it's pretty straight forward, as long as you have all of the right connection information (and understand the schema of the directory).  I would be happy to post the code if anyone is interested.  Short of that, here are some of the discoveries I've made:

  1. You can use the standard System.DirectoryServices.Protocols.LdapConnection class to connect to OID.  Here's the generic code I used:

    LdapDirectoryIdentifier _identifier = new LdapDirectoryIdentifier(ldapServerName, portNumber);
    connection = new System.DirectoryServices.Protocols.LdapConnection(_identifier);

  2. You need to override the Initialize member of the base membership class to supply the various connection settings you'll need.  There's a NameValue collection that's passed to this member built from the properties on the provider information you have to supply in Web.Config.  In my case, I limited my settings to LDAP server address (name or IP address), the LDAP port (originally my client suggested they used a non-standard port), Application Name (a property you must override when developing a custom membership provider) and LDAP domain (e.g. dc=com,  dc=customer).   The MOSS supplied provider is a bit more flexible, but I didn't particularly need all of that flexibility (read "complexity").
  3. I had to add the same provider information to Central Administration as I did for my SharePoint site.  I didn't change the authentication method on Central Admin, but without adding the provider, I could not get the people picker (in my SharePoint site) to resolve the user IDs from OID.  Once I added the provider all worked well.  In fact, in some cases, it seems that Central Admin "knows" about the user before the SharePoint application.
  4. You have to overload the following members in the base membership provider in order for it to work with SharePoint
    1. ValidateUser (the member that actually ensures the user is who they say they are)
    2. GetUser (both versions)
    3. GetUserNameByEMail
    4. FindUsersByName
    5. GetAllUsers

      An article published on MSDN defines the minimum interfaces: http://msdn.microsoft.com/en-us/library/bb975135.aspx#MOSSFBAPart2_DevelopingCustom
  5. You don't necessarily have to authenticate with the directory to exercise most of the members above, with the exception of ValidateUser.  In my case, my client's OID implementation enabled anonymous access.
  6. The act of "binding" to the LDAP directory validated the user.  That said, this only worked for users in the directory.  If I passed a user that did exist, but provided the wrong password, the validation failed as expected.  If, however, I passed a non-existent user to the directory (regardless of the combination of user ID and password), the Bind() method did not return any errors and my "authentication" worked.    I'm not sure if I've missed something or if this is unique to LDAP, but it was a strange behavior.  During my development I used a tool called LDAP Admin (http://ldapadmin.sourceforge.net/).  The tool was invaluable for validating connection information and user data.  It also, however, suffered the same fate as my code -if I tried to authenticate a user that didn't exist, the connection would be successful.  Weird.
  7. My client also wanted to use a single sign-on service provided by OID.  The service is quite flexible, supporting three different methods for supplying credentials to target applications - GET, POST and BASIC..  Unfortunately, since we configured the site with a custom membership provider, the only options were either GET or POST.  We chose post.  Unfortunately, the standard login page doesn't seem to want to allow a post from another page (although I didn't spend a long time to work it out).  I ended up constructing a basic page that took in form properties and then used the Membership class to authenticate the user and redirect them back to the SharePoint site.

Ultimately, the new provider works well and the SharePoint site is integrated with the SSO server.  User's who have access to my client's Oracle Portal can seamlessly access their SharePoint site as well  -- all without having to authenticate a second time.  And, because both web sites use the same LDAP, there's not need to synchronize user IDs and passwords.

Again, if you're interested in the code, just drop me a line; if I get enough requests, I'll post the code directly.

[UPDATE 6 SEPT 2010] The code has been posted on a new article about connecting SharePoint to Oracle LDAP

19 March 2008

Customized My Sites Exposed

We recently undertook a project to develop a global intranet for a relatively large organization.  As part of the requirements of that implementation, the client wanted to create a highly customized My Site experience.  As anyone who has delved deep into My Site customization knows, it's not straightforward, easy and may create maintenance issues long term. 

Ultimately, after working through the challenges with the client, we collectively agreed to back off the more grandiose My Site customization plans in lieu of a more simple approach.  The reasons for this change centered around the following:

  • Each My Site is a site collection and dealing with several thousand My Sites when need to change elements of the implementation was not something the client wanted to deal with long term
  • The original plan the client had for the My Site, while useful, ultimately removed a good deal of useful functionality provided by Microsoft
  • There was some concern about "upgradeablility"

So while the we didn't create the highly customized My Site, we still implemented some limited customization that delivered a custom theme, master page and some unique navigation (to tie in the rest of the portal).  We used a technique called "feature stapling" to make that happen and ensure "compatibility" with what Microsoft would like to see in SharePoint implementations.

If you're interested in a really good set of explanations of both the My Site architecture, see a blog entry from Mark Arend.  If you are looking for the best practice approach to modifying the My Sites, see the SharePoint Product Team's blog entry.