All posts in SharePoint 2010

Quick Tip – jQuery click to expand / collapse Quicklaunch – UPDATED 20/06/2012

jquery_collapse_accordion

Hello everyone, following on from the previous Quick Tip I have yet another cool little snippet of jQuery code to enable a manually collapsable quicklaunch.  Many users who have downloaded my Metro UI masterpage commented if there was a way to have the hover quicklauch accordion replaced with a clickable version.  Well your requests have been answered and below is a snippet that will work on any v4.master page.  I have included some comments within the source code to help you out.

I hope that this code is what you were hoping for, and i will soon be updating the Metro Masterpage for Farm Solutions to include an option to choose your accordion type and a Metro UI version of the code.

As always comments / issues always welcome :)

UPDATE 20/06/2012.

Thanks to Anastacia for pointing out the issue with the script in Firefox.  I have updated the script to fix this issue by placing the anchor in a different location and updating the rest of the script. Please use the new script above which solves the issue.  Chris

 

EU Cookie Law & SharePoint – What’s affected?

cookies

What is the new EU Cookie Law?

The EU Cookie Law is intended to prevent information being stored on people’s computers, or to be used to recognise them through the device they are using, without their knowledge or agreement. The rules are not intended to restrict the use of particular technologies.  The deadline for compliance with the Cookie Law is the 26th May 2012. All websites in the UK must comply with the Information Commissioner’s Office guidance on the use of cookies, gain informed consent from your site visitors, or face up to a £500,000 fine.

What Kinds of Cookies are affected?

There are different types of cookies, and this new law applies to all of them:

Session cookies
These save information about your current viewing session – for example:

  • If you are logged in
  • If you have added items to the shopping basket

These are often less of a privacy concern as they only last for the duration of your browsing session and are generally required for the function of a website.

Persistent Cookies
A persistent cookie is stored on your device and generally remembers your preferences across one or many websites. Some examples are:

  • Whether you want to view comments in threaded or flat view
  • What font size you want to view the site in
  • What language you want to view the site in

First party cookies
First party cookies are set by the same domain that you are visiting – for example to authenticate you with that site.

Third party cookies
Third party cookies are set by websites other than the one you are visiting, and these tend to be in the ‘shady area’ when it comes to privacy. For example, when you visit a site it might store a cookie called ad.myadvertisingcompany.com. When you visit another site, it might store another cookie similar to this. Eventually the information is sent back to My Advertising Company to build up a profile of your web activity. (Note most browsers allow you to block 3rd party cookies)

What will happen if i do nothing?

The first thing to remember is that there are millions of websites on the internet, and many of them are personal blogs such as this one.  There are going to be millions of casual bloggers who have no idea what a cookie is, let alone how to comply with the new law.  Below is an extract from the ICO website explaining what they can do if they are not compliant.

Information notice: this requires organisations to provide the Information Commissioner with specific information within a certain time period.

Undertaking: this commits an organisation to a particular course of action in order to improve its compliance.

Enforcement notice: this compels an organisation to take the action specified in the notice to bring about compliance with the Regulations. For example, a notice may be served to compel an organisation to start gaining consent for cookies. Failure to comply with an enforcement notice can be a criminal offence.

Monetary penalty notice: a monetary penalty notice requires an organisation to pay a monetary penalty of an amount determined by the ICO, up to a maximum of £500,000. This power can be used in the most serious of cases and if specific criteria are met, for example, if any person has seriously contravened the Regulations and if the contravention was of a kind likely to cause substantial damage or substantial distress. In addition, the contravention must either have been deliberate or the person must have known or ought to have known that there was a risk that a contravention would occur and failed to take reasonable steps to prevent it.

How do i know what Cookies my site uses?

Many companies on the internet are providing services which are called Cookie Audits.  Having not paid for one of these, I can only assume they deliver on the price tag being asked for (some of them are £300+). Most will promise to analyse your website and inform you of all the cookies your site uses, comparing them with a reference database to provide you with a report.  If you have a very large site, with hundreds if not thousands of pages, then this may be money well spent.  On the other hand, if you have a smaller site then you can do some of the research very easily with a free Firefox extension called View Cookies.  After installing View Cookies, you will find a new Cookies-tab in the Page Info dialog box. You can open the Page Info dialog box by selecting Page Info in the Tools menu. You can also right-click on the webpage and select View Page Info from the drop down menu.

Using this extension should help the majority of users on the internet get a general view of the scale of the cookies.  This blog for example has three cookies for Google Analytics. As of the deadline, these cookies will require the user to “allow” these to be used and set.

IMPORTANT: The UK law does not allow you to retrospectively set cookies and then delete them if the user opts out.  You have to ensure that they are only set after user confirmation.

How does this affect my SharePoint Site?

It is important to know that technically, even Intranets are covered by this law.  The framework will insist that websites ask their users for permission before recording their activities online. The implication is that if you use cookies on your intranet, you may have to ask for your employee’s permission first.

I have done some initial research, and I will try my hardest to keep this updated on cookie usage information. SharePoint 2010 uses cookies to log session information, Web Analytics, and FBA Login information.  There is a cookie called “OfflineClientInstalled” which is set on the settings pages, which I can assume could be something to do with SharePoint Workspace Manager or possibly Office?  Others found on list view pages are “stsSyncAppName” and “stsSyncIconPath”, which I am still investigating.

If you find any commonly set cookies or have any information on the ones listed above, please leave a comment and we can try to build up a repository of cookies and their purpose.

How do I make my site EU Cookie Compliant?

One of the most common solutions for becoming compliant will be through the use of Javascript code. The code will create a cookie to store the users preference and then depending on their response, additional Javascript code would set or remove cookies.

There are many different solutions you can use to present the user with the information:

  1. Modal Dialogue
    Using a modal dialogue would be the most intrusive method to ask users for permission.  It is a simple enforced call to action which will outline the reasons for the cookies you would like to set.  The problems with this method is that it will prevent users from interacting with the website and could increase the bounce rate from your site.
  2. Status Bar
    Subtle status bars on the top or bottom of a website can be included to inform users about the cookie policy.  This would remain on all pages until they either accept or decline cookie usage.  While this is less intrusive than the previous solution, it could be so subtle that a user never opts into the usage agreement, and functionality may be reduced for the visitor.
  3. Warning Panel
    A warning panel is similar to the previous option however it has the advantage of informing the visitor to your site what setting the page is using.  Downsides however are that a user may not decide to opt in and a warning bar would obscure parts of the page.

Which option you decide to go with is up to you, as all options have pros and cons.  If you have any other suggestions for how you could accomplish the task, please feel free to share your ideas.

After some quick searching online, one of the better solutions I found was “Simple Cookie Prompt” (http://www.pandadoodle.com/cookies/)  This lightweight Javascript code places a subtle status bar message for users at the top of each page and then sets one of four options depending on answer.

There are 4 possible returned values:

  1. The user has actively opted out of all cookies on the site. Shows the red notification.
  2. The user has seen a warning about cookies, but neither accepted nor declined, this is classed as inferred acception. Shows the blue notification
  3. The user has accepted all cookies to the site. Shows the green notification.
  4. The user’s first visit to the site, no cookies accepted or declined. Shows the yellow notifcation

Using a small piece of JS code to wrap around your existing code is as simple as this:

Summary

The EU Cookie Law itself is nothing new, however with the pending deadline, companies are becoming increasingly worried about their compliance.  I have noticed only a handful of UK taking steps to become compliant e.g. (http://www.bt.co.uk/) and I’m sure that in the coming months all the big players will be compliant.  If you have a simple website, then becoming compliant will be relatively straight forward, however if you are running a highly complex e-commerce site or one with detailed user customisation, then you will have a much tougher battle on your hands.  Please give me your feedback on your thoughts about this issue, and how you are going to make your SharePoint website / intranet EU Compliant.

iGoogle UI for SharePoint 2010 – Part Four: Control Adapters

Series Content

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

Overview

In Part Four we will take the take a look at how we will create our widgets in SharePoint 2010.  As the title of this post mentions we are going to use what is known as a Control Adapter.  This Post will outline what they are, how they work, and how we are going to use them in this series.  There will also be a code snippet to explain how we can use it.

Control Adapters

Rather than try to explain these myself I thought it would be easier to grab a snippet from a Microsoft Article which i think does a great job of explaining what and how they work from an architectural level and in more detail than I could probably achieve :).

At their core, control adapters are simply a way of providing different renderings for controls without actually modifying the controls themselves. Because control adapters are designed to provide alternate renderings for different clients, you specify control adapter mappings in a .browser file, which is where associations between User Agent strings and browser capabilities are defined. The control adapter class itself must inherit from the System.Web.UI.Adapters.ControlAdapter, which is an abstract base class that looks much like the Control base class, with events for Init, Load, PreRender, and Unload, as well as a virtual Render method.

The next step to use a control adapter is to derivatively bind your adapter to a specific control.  To do this you use a Browser Definition File Schema which is found in the App_Browsers folder of the IIS WebSite you are using.

How are we going to use Control Adapters?

Now we know what a control adapter is, what do we need them for?  Well, if we are going to have our WebPart rendering like we have built in the previous three post then we will need to use a Control Adapter to do the hard work for us.  WebParts can be placed onto a SharePoint 2010 Page in many ways.  They can be either added to content inline using the rich content editor, they can be added directly into a page layout or masterpage, or (the most common way) is that they can be placed into a WebPart zone.  It is this final method that we are going to use to modify the rendering of our WebParts.

A basic WebPart Control Adapter Code looks like this:

As you can see from the code above we have a class which inherits from System.Web.UI.Adapters.ControlAdapters.  We first get a reference to the current WebPartZone on the Adapter.  If this is not null then we can start to override the WebPart rendering.  We then check how many WebParts exist in the current WebPartZone that we are in and if there are some then we create a new WebPartCollection object with all the WebParts in the current zone.

We can then loop through each WebPart in the collection and render the WebPart control.   This alone will remove all the tables for each WebPart rendered in a WebPartZone.  The final step to get this basic Control Adapter working is to update the compact.browser file stored (in my case) in the inetpub > webapp > App_Browsers > compact.browser file.

We need to add a single line into the <controlAdapters> node to register our new custom adapter.

Save this file and ensure that the dll is in the GAC and then the control adapter should work.  One thing that is important to know about Control Adapters is that when they are in use they will by default process EVERY WebPart on the site.  For our implementation however we want to be able to choose which WebParts are rendered as our widgets.  To do this we will place some logic into our control adapter which will check the title of the WebPartZone to ensure it contains the text “iGoogle” and only process WebParts that are contained within those specific zones.  Another piece of logic that we need to place into our zones is that we only want our rendering to process WebParts when the page is in the Display mode and not in Edit mode.  The code below shows the updated adapter with the new pieces of logic included.

As you can now see we have first added a line to get a reference to the current WebPartManager on the page which will enable use to get the state of the page and check if we are in display or edit mode.

We are then able to set a boolean value to the state of the page.

The final step is to wrap a new if statement around the render code which will control when the table removal is processed.

When this code is run only WebPartZones with the iGoogle text value in the title will be rendered.

Adding the Widget Code Wrapper

Now that we have the basics sorted for our Control Adapter we now need to wrap our widget code around the render control and this can be done like it would be done in a normal WebPart.  We need to add the following code and replace it within the foreach loop around for each WebPart.

Those who have been following the previous three posts will recognize the HTML from above.  I have use the writer object to inject the HTML and have also ensured that the ID of my widget wrapper div is generated from the current WebPart ID – (wp.ID), and the title of the WebPart is injected into the <H3> tag.

Summary

That wraps up part four of the iGoogle series.  The next post will be to integrate the code above into a SharePoint 2010 solution and include some of the extra pieces such as CSS to enable the this solution to come to life.  The final code for this Control Adapter is shown below.  Thanks for reading and all the positive feedback is greatly appreciated.

 

iGoogle UI for SharePoint – Part Three: Saving WebPart states using Cookies

Series Content

  1.     Part One – Overview, Concept,  HTML Structure & jQuery Basics
  2.     Part Two – Dragging, Dropping,  Sorting and Collapsing
  3.     Part Three – Saving WebPart states using Cookies – Current Article
  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

In Part Three we will take the code from our previous post and enable the page to remember the state of the various settings that we have applied such as the WebPart positions, the order, and minimise states and the webpart header colours.

Javascript

For this post we will require a new javascript library to help manage the Cookies stored for each user.  This library has been already included at the bottom of the existing demo’s.  This time however we will finally use it.  This Post will contain a lot of new Javascript and I will try my best to explain all of the items.

Saving the Position

The First thing that we will do is to Save the Position of all of the widgets at different times in the page life-cycle.  The first thing we need to do is dynamically set the Zones setting previously defined in previous posts. as well as add another setting into the definition to store the Cookie settings.

This parameter was left blank on purpose to give the script the maximum flexibility.  So to find out where the widgets are we need to find out what “zones” that the widgets are occupying.  To do this we will create a new function called “defineZones” which will be used to iterate through the DOM and create a comma separated list of zones and their ID’s.  Now a Zone in this tutorial is the ID associated with each column.

The full function is shown below. We will then dive into the details of the code.

Lines 6 – 9 goes through all of the columns defined in the settings.columns property and then creates the string based on the current items ID.  In line 11 i then set the dynamic string to the zones parameter only after trimming the end of the string again.

Now that we have a set of defined zones we need to now set up a new function to save the state of all the widgets contained with each column.

This new function SaveState does the following actions.  To this method we will add first create a new reference to our global object and then we update the Badge Details in-case something new has changed.

We then create a new cookie with the setCookie() method which will use the positionCookie setting to store the cookie key and then call the GetPositionState() method which will return the positions as a comma separated & pipe separated list.

The GetPositionState() method firstly gets a local array of all of the zones we found using the previous method and add it into a new zone variable. Then we create a blank string value to store our positions.  Next we loop through each zone and for that we use the jQuery sortable methods with the “toArray” parameter which will get a comma seperated list of all of the zones and seperate each zone with a pipe character.  Finally we will create a javascript alert of the widgetPositions found.

Next we place the SaveState(); method call into the remove button event handler, as well as the stop method of the makeSortable method so that when we remove or move a widget on the page it will provide us with the new position.

At this stage we now can save the position of each widget when we close and move them on the page between columns.

Retrieving the Position & Order

The next step is to now to retrieve the position of the locations when you load the page so that the widgets appear in their previous positions.  To do this we need to firstly create a new method in our iSharePoint Namespace called loadStateFromCookie. This method will do two things.  Firstly it will load the position state from the cookie and place it into a variable, and then it will pass this to another method ProcessWidgetPositionData which will place the widgets in the correct locations.

As you can see we firstly get a reference to the settings and the local jQuery object.  We then set a custom variable PositionStates to the cookie value by using the getCookie method.  We then pass this into the ProcessWidgetPositionData method and then finally we update the badge method which will ensure that the number of “closed” widgets is correct.  We will now dissect the processing function.

This method is quite long but is easier than it appears.  As we have done for each method so far we need to get our local references to jQuery etc, and then we need to check that we have received some data in the PositionStates variable.  Next we need to split the array of values which we created in the SaveState() method back into an array so that we can loop through them.  We will also need to get the array of zones defined so that we can match up each of the arrays.

Next step is to loop through each of positions in the order array and perform two important tasks.  The first task is to place the correct widgets in their correct columns and then the next step is to ensure that they are in the correct order in that column.  We will firstly tackle the positions:

What this first part of the function does is loops through all of the widgets on the page when it loads and search if the current widget is found in the order variable (using the .search method, if an item is not found then it will return -1) then we want to add that item to the current column (defined in the zonearray).  NOTE: Because we are in control of the order that values are saved into the cookie the retrieval of the items can be predictable.

The next step is to then reorder the widgets in the current column.

This will again ensure that there is a value in the current order value (there can be a column with no items) and then it will split the widget values into an array.   We now have an array of values which are in the order that they were saved so we can now process the array by appending the widgets in the current column again but this time in the correct order.  Simple. :)  The complete code for this method is shown below:

 

Demo

To view a demo of where we have got to thus far click here

Saving the Collapsed State

The next step is to save the collapsed state of each of the widgets on the page.  The first step is to modify the SaveState(); function to include the following line at the end.

This line does what it say and sets the minimiseCookie to the value that is returned from the GetMinimisedState() method.  The GetMinimisedState() is a new method which is going to be added outside of the iSharePoint namespace and will simply go through each widget which has the minimised class attached to it and add it to an array.

That’s it for saving the collapsed state ..nice and simple.

Retrieving the Collapsed State

To retrieve the collapse state is also another simple addition.  To do this we will load the state from the cookie set above and then for each of the widgets defined in the array it will set them to minimised and collapse the widget.

So the first step is to modify the loadStateFromCookie function to include two lines.  The first line is to set a local variable “MinimisedStates” to the cookie value:

the next step is then to process that data by passing it into a ProcessMinimiseData() method.

What this processing method does is split the array of MinimiseStates and then for each item in that array it will locate the widget with that ID.

If there is a widget in the array it will perform a slideToggle and then add the minimised class to the current widget.  The final step to this piece of the puzzle is to ensure that when you click on the button to minimise each widget is to run the save state method.  To do this we just modify the buttonFunctions method with the highlighted item below.

That’s it for this section. :)

Demo

To view a demo of where we have got to thus far click here

Saving the Colour

This section we will save the current colour set in the webparts colour settings panel.  As we built in previous posts the colour widget can be any colour you can think of so we need to find a way to process this data on the fly.  Once again like above we need to modify the SaveState(); function to include another line at the end.

Like before this will set the cookie to the output from the GetWidetColor method.  This method simply goes through each widget and gets the value that is stored in the text box with the class iColorPicker.

When the method loops through each text box it will also pipe delimit the widget id along with the colour so we are able to match them up on retrieval.  Next step..getting the colour back on load.

Retrieving the Colour

To retrieve the colour of the widget is very similar to the previous “retrieve” methods. To do this we will load the state from the cookie set above and then for each of the widgets defined in the array it will set them to colour defined and then re-color the widget.

So the first step is to modify the loadStateFromCookie function to include two lines.  The first line is to set a local variable “ColorStates” to the cookie value:

the next step is then to process that data by passing it into a ProcessWidgetColorData() method.

What this processing method does is split the array of ColorStats and then for each item in that array it will find the widget with that ID using jQuery.Find() and set the Text Box Value, CSS and Handle Selector CSS.   The first couple of lines should be all too familiar by this point.  Below is the full method:

That is all that is required for the colour modifications..we are almost done now :)

Demo

To view a demo of where we have got to thus far click here

Resetting Layout

The final step we need to implement for the base functionality is the ability for the user to “reset” his / her layout back to the predefined default.  To do this we need to add 5 lines of javascript into the buttonFunctions method into the reset button click event.

All this does (its pretty obvious) is delete each of the user set cookies and loop through each colour picker text box and clear the values which will reset the colours.

Summary

So that’s the end of part 3 of this blog series.  It has been quite a long one but i hope that you have all learned something from this and can see how easy it is to combine jQuery and HTML to create a really great interface.  The full js for this post is shown below.  I will be hoping to get the next posts completed faster next time.  Please leave your comments..they are always appreciated.

Metro UI – SharePoint Masterpage for Sandbox Solutions

Just a quick note that i have updated and created a blue themed wsp which now works in a Sandbox Solution.

http://lifeinsharepoint.codeplex.com/releases/view/78033

Hope this helps some people.