Archive for August, 2011

iGoogle UI for SharePoint – Part One : Overview, Concept, HTML Structure & Jquery Basics

iGoogle---Part-One

Series Content

  1.     Part One – Overview, Concept,  HTML Structure & jQuery Basics – Current Article
  2.     Part Two – Dragging, Dropping,  Sorting and Collapsing
  3.     Part Three – Saving WebPart states using Cookies
  4.     Part Four – Control Adapters
  5.     Part Five – SharePoint 2010 Integration
  6.     Part Six – Bringing it all together
  7.     Bonus – Saving WebPart States using the Client Object Model

Overview

This is the first in a series of posts which will explain how to create an iGoogle style interface for SharePoint 2010.  More and more clients are asking for an iGoogle or BBC Homepage style homepage for their intranets and out of the box in SharePoint 2010 there is no method to do this.  While you can drag and drop webparts in “Edit Mode” in a WebPart page, end user however is stuck on where to place their webparts on the page.  This series will aim to provide a mechanism where end users are able to take control of their page and make the SharePoint experience more personal.

There are many sites on the internet which have the ability to drag and drop components around the page and save their locations for your next visit.  Some of the most well known examples of this interface are:

iGoogle – http://www.google.com/ig?hl=

BBC Homepage – http://www.bbc.co.uk/

Both these sites give you the ability to drag and drop various widgets around the page.  You can also close widgets you do not want to see and minimise others to maximise space on the page.  This is the kind of interface that we are going to create for use in SharePoint using jQuery and some C# code.

The Plan

First, let’s list exactly what we’ll be creating here and what features it will have:

  • The interface will contain several widgets (WebParts).
  • Each widget can be collapsed and removed via controls on the page.
  • The widgets can be sorted into an unlimited number of columns.
  • WebParts will be have their rendering controlled via a control adapter which will modify their look and feel.
  • Widgets will have their location and states saved using cookies.
  • Creating a simple Visual Studio 2010 solution to deploy an example.

This post will provide an overview of what we are planning to build as well as getting some development environments configured for your own personal demos.

Getting Started

To get started in this post we will be creating a demo environment to ensure that the Javascript, HTML and CSS are all working together for use in future posts.  Initially we will not be touching SharePoint as it is not necessary at this stage.  Firstly we will need to create a base HTML template that will load a specific CSS stylesheet, images and Javascript libraries.

HTML

Below is the base HTML that will be used in our initial demo.  We have a wrapper div that surrounds three div columns called “Left”, “Middle” and “Right”.  Within each column is the widget HTML that will be used to wrap each WebPart.  Each widget has a wrapper div as well as a header and body content divs.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

	<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame. Remove this if you use the .htaccess -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

	<title>Life In SharePoint - Drag and Drop - Part One</title>

	<link rel="stylesheet" type="text/css" media="all" href="css/style.css" />

</head>	

<body>

	<div class='wrapper'>

		<div class='column' id='left'>
			<div class='widget' id='111'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 1</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color111' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
			<div class='widget' id='2'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 2</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color2' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
		</div>		

		<div class='column' id='middle'>
			<div class='widget' id='3'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 3</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color3' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
			<div class='widget' id='4'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 4</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color4' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
		</div>		

		<div class='column' id='right'>
			<div class='widget' id='5'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 5</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color5' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
			<div class='widget' id='6'>
				<div class="widget-head">
					<a class='collapse'>collapse</a>
					<h3>Widget title 6</h3>
					<a class='remove'>remove</a>
					<a class='edit'>edit</a>
				</div>
				<div class="widget-edit">
					<input type='text' type="text" class="iColorPicker" id='color6' />
					<div class='clearfix'></div>
				</div>
				<div class="widget-content">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lorem orci, ornare at malesuada a, pulvinar lobortis neque. Integer et felis vel augue suscipit vestibulum id nec nulla.</p>
				</div>
			</div>
		</div>
	</div>
	<div id='toolbox-wrapper'>

		<div id='toolbox-controls'>
			<div class='badge'></div>
			<p class="slide"><a href="#" class="btn-slide">Toolbox</a></p>
			<p class="reset"><a href="#" class="btn-reset">Reset Widgets</a></p>
		</div>
		<div class='column' id='toolbox'>

		</div>
		<div style='clear:both;'></div>
	</div>	

	<!-- Load the jQuery Libraries -->
	<script src="js/jquery-1.6.2.min.js" type="text/javascript"></script>
	<script src="js/jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
	<script type="text/javascript" src="js/iColorPicker.js"></script>
	<script type="text/javascript" src="js/jquery.cookie.js"></script>
	<script type="text/javascript" src="js/jquery.corner.js"></script>
	<!-- script file to add your own JavaScript -->
	<script type="text/javascript" src="js/script.js"></script>	

</body>
</html>

As you can see the HTML is very simple but at the moment it will not look very attractive.  We have each of the widgets in their own Div and in the header we have three images which will be our “buttons” to control each widget.  On the left we have the collapse icon, next we have the edit icon and finally we have the remove icon.  Underneath the header we have an edit panel which will contain in this example some colour selections for the header bar which will be hidden in the css shown below.  So the next task is to now style the page and make it look neater.

CSS

The CSS is fairly simple and will be used for the SharePoint implementation.  We start with a global reset of the page to ensure that all DOM elements are reset.

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center,dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed,  figure, figcaption, footer, header, hgroup,  menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%;	font: inherit; vertical-align: baseline; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {	display: block;} body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; } 

/** Base Body Styles **/
body{ background:#ddd; color:#000; font:14px Arial, Helvetica, "Trebuchet MS", sans-serif;}

h1,h2,h3,h4,h5,h6{ font-weight:bold; }
h1{ font-size:30px;}
h2{ font-size:24px;}
h3{ font-size:18px;}
h4{ font-size:14px;}
h5{ font-size:12px;}
h6{ font-size:10px;}

a{ text-decoration:none; }
a:active, a:visited { color: #607890; }
a:hover { color: #036; }

.wrapper
{
	clear:both;
}

.column
{
	float:left;
	width:300px;
	margin:10px;
	min-height:100px;
}

.column .widget {
	border:1px solid #ddd;
	margin:5px;
	width:288px;
	float:left;
	background-color:#fff;
}

.widget-head
{
	background-color:#60b51c;
	padding:5px;
	margin:5px 5px 5px 5px;
	height:20px;
}

.widget-head h3
{
	float:left;
    padding: 0 5px;
	color:#fff;
	font-family: verdana, arial;
	font-weight:normal;
	font-size:1em;
}

.widget-head a.remove  {
    float: right;
    display: inline;
    background: url(../images/controls.png) no-repeat -14px 0;
    width: 14px;
    height: 14px;
    margin: 3px 4px 0px 0;
    text-indent: -9999em;
    outline: none;
}  

.widget-head a.edit  {
    float: right;
    display: inline;
    background: url(../images/controls.png) no-repeat -28px 0;
    width: 14px;
    height: 14px;
    margin: 3px 4px 0px 0;
    text-indent: -9999em;
    outline: none;
}  

.widget-head a.collapse  {
    float: left;
    display: inline;
    background: url(../images/controls.png) no-repeat 0;
    width: 14px;
    height: 14px;
    text-indent: -9999em;
    margin: 3px 0 0px 4px;
    outline: none;
}
.widget-edit
{
	background-color:#efefef;
	border:1px solid #ddd;
	padding:5px;
	margin:0px 5px 5px 5px;
	display:none;
}
.widget-edit ul
{

}
.widget-edit ul.colors li {
    width: 20px;
    height: 20px;
    border: 1px solid #EEE;
    float: left;
    display: inline;
    margin: 0 5px 0 0;
    cursor: pointer;
	background-color:red;
}  

.widget-content
{

	padding:5px;
}
.widget-placeholder
{
	border:2px dashed #999;
	margin:5px;
	width:283px;
	float:left;
}

#toolbox-wrapper
{
	clear:both;
	width:900px;
	margin:10px;
}

#toolbox-controls
{
	float:left;
}

#toolbox
{
	background-color:#fff;
	padding:5px;
	width:930px;
	min-height:auto;
	margin:0px;
	margin-top:-1px;
	border:1px solid #ddd;
	float:left;
	position:relative;
}

#toolbox .widget
{
	float:left;
}

#toolbox .widget-content, #toolbox .widget-head .collapse, #toolbox .widget-head .remove, #toolbox .widget-head .edit
{
	display:none;
}

.badge {
	background-image: url('../images/badge.png');
	width:20px;
	height:17px;
	float:right;
	color:#fff;
	padding-top:4px;
	text-align:center;
	font-size:10px;
	font-weight:bold;
	position:absolute;
	z-index:10;
	margin-left:-5px;
	font-family:verdana;
}

.slide {
                margin: 5px 5px 0px 0px;
                background-color:#fff;
                float:left;
                color:#fff;
				border:1px solid #ddd;
				position:relative;
}

.slide a, .slide a:active, .slide a:visited
{
                float:left;
                color:#fff;
                padding: 5px;
				margin:5px;
				background-color:#187069;
}

.reset a, .reset a:active, .reset a:visited
{
                float:left;
                color:#fff;
                padding: 5px;
				margin:5px;
				background-color:#082167;
}

.reset {
				margin: 5px 5px 0px 5px;
                background-color:#fff;
                float:left;
                color:#fff;
				border:1px solid #ddd;
				position:relative;
}

The CSS helps style the page into three even columns and each of the widgets are styled with some buttons and styled headers.

Javascript

To provide the cool functionality, we will need to get the latest jQuery libraries and jQuery plugins. We will also create our own custom javascript file which we will be used to store our script.  The versions that we are using are below with links to download them.

Our own script.js file at this stage will contain only a couple of lines of code to test that jQuery is working;

jQuery(document).ready(function(){
	alert('Jquery is Working');
});

Images

The images for the close and collapse buttons we will use a simple sprite which has a close, max and min symbols on it.

Live Demo

A live demo of the base structure can be found here.

Summary

In this post we have outlined what we will be covering and have managed to get a demo environment working for the next phase.  We will add some jQuery functionality and make our page come alive in the next posts.  I hope this post has been useful and please leave some comments about what you would like to see in future posts.

 

SPLongOperation – Explained & Branded

Processing

Overview

When you are performing out of the box operations in SharePoint 2010 normally in Central Administration you will get a nice loading screen from SharePoint with an animated loading gif.  Have you ever wondered how you can use this in your own SharePoint Solution?  I have been doing SharePoint for a while now and only recently discovered the SPLongOperation method and it is quite the little gem.

SPLongOperation.BeginOperation beginOperation = null;

if (beginOperation == null)
{
    beginOperation = delegate(SPLongOperation longOperation)
    {
        // Long running code here ..

        longOperation.End("settings.aspx", SPRedirectFlags.RelativeToLayoutsPage, HttpContext.Current, null);
    };
}
SPLongOperation.Begin(beginOperation);

I have been writing a site provisioning service recently and have used the above code to help provide the end users some feedback while a new site collection is being created.  Only a couple of lines of code but it transformed the solution.

Want to change the text that is displayed in the loading screen?  No problem.

// BEGIN SPLongOperation
SPLongOperation longoperation = new SPLongOperation(this.Page);
longoperation.LeadingHTML = "<div><h2>This is the main Title</h2></div>";
longoperation.TrailingHTML = "<div><h3>This is the second line of text underneath</h3></div>";
longoperation.Begin();

// long running code here

// END SPLongOperation
longoperation.End(Customers.DefaultViewUrl, Microsoft.SharePoint.Utilities.SPRedirectFlags.Default, this.Context, "");

This will change the text on the page to reflect your specific requirements.

Branding the Loading Page

Do you want to match the loading page to your corporate colour scheme?  No problem.  Below is the output of the page in raw html.

<body onload="setGearPageFocus();gotoNextPage();" class="s4-simple-gearpage">
	<div id="GearPage">
		<div id="s4-simple-card" class="s4-simple-gearpage">
			<div id="s4-simple-card-content">
				<h1>
					<a id="gearsImageLink" href="javascript:;" onclick="hideGears();" title="This animation indicates the operation is in progress. Click to remove this animated image." >
						<img id="gearsImage" alt="This animation indicates the operation is in progress. Click to remove this animated image." src="/_layouts/images/gears_anv4.gif" style="width:24px; height:24px; font-size:0px;" align="absmiddle" />
					</a>
					Processing...
				</h1>
				<div>
					Life In SharePoint Long Operation Demo
				</div>
				<div>
					<br /><br />This is a custom long operation text
				</div>
			</div>
		</div>
	</div>
</body>

As you can see the markup is very simple.  What you can then do is create a new CSS style sheet and inject the reference to it in the LeadingHTML property as the property is not escaped.

longoperation.LeadingHTML = "<link rel='stylesheet' href='/_layouts/LifeInSharePoint/LongOperation.css' type='text/css'  />Life In SharePoint Long Operation Demo";

This will then enable you to customize the page as you need to changing background colours, fonts images etc.  This is the kind of result that you will get.

Do download a working solution with branding included please use the link below.

LISP.LongOperationDemo.zip