Friday, May 4, 2012

Show & Hide Ribbon in MasterPage with Keyboard Shortcut

Hello Everybody,
Many of us are required to create master-pages that hide the ribbon part but still enable using it when in admin mode.

One way to do it would be to surround the ribbon area in the master-page with an SPSecurityTrimmedControl and show that part only when administrators are connected to the page, but that method makes life a little hard because whenever you want to check the design you are not able to see the page as a simple user sees it unless you actually log in as a different user. Moreover, you are required to Check-In\Out the page\css\js to see the changes with a simple user.

In this post I would like to show you the way to add the Keyboard Shortcut Ctrl + G as an option to Toggle (Show and Hide) the SharePoint Ribbon part of the Master Page. This means that the ribbon will be hidden by default and any user can activate it by knowing and\or the Key Combination of Ctrl + G.

The part we will be hiding\showing

We will need 4 components
  1. jQuery (To enable the code to run)
  2. jQuery Cookie plugin (To enable saving the ribbon state between post-backs)
  3. Some custom code (To perform the changing of the ribbon state)
  4. Some custom css to add to a style sheet (only 1 line)
// This file needs to come with the following files:
// jQuery.js
// jQuery.cookie.js
//
// Also the following css needs to be added to the masterpage css:
// style.css : #s4-ribbonrow { display:none; }

var RibbonDisplayCookieName = "ESSCKI_DisplayMode";
var CtrlGControlsToHide = "#s4-ribbonrow";
// Adding functionality to catch 'ctrl' key press combo
$.ctrl = function(key, callback, args) {
    $(document).keydown(function(e) {
        if(!args) args=[]; // IE barks when args is null
        if(e.keyCode == key.charCodeAt(0) && e.ctrlKey) {
            callback.apply(this, args);
            return false;
        }
    });
};

// Registering 'ctrl' + 'G' button press
$.ctrl('G', function(s) {
    var ribbonElement = $(CtrlGControlsToHide);
    var displayPropValue = (ribbonElement .css('display') == 'none' ? 'block' : 'none');
    ribbonElement.css('display', displayPropValue);
    
    // Set display state for the following hour
    var date = new Date();  
    date.setTime(date.getTime() + (60 * 60 * 1000));  
    $.cookie(RibbonDisplayCookieName, displayPropValue, { expires: date });
     
}, ["Control G pressed"]);

// Loading cookie value of ribbon display
if ($.cookie(RibbonDisplayCookieName) == 'block')
    document.write("<style> " + CtrlGControlsToHide + " { display:block; } </style>");

Last Component - CSS
As it is stated in the snippet above, you need to add the following css rule to a css file on the page:
    #s4-ribbonrow { display:none; }

Please note two things:

  • The css you are adding this file needs to appear before the js code file
  • If the jQuery code does not work, you should try adding var $j = jQuery.noConflict(); to the code snippet and change all $ occurrences to $j.
24/05/2012 Update: Added CtrlGControlsToHide variable to be able to hide several controls on the page with Ctrl + G like CtrlGControlsToHide = "#s4-ribbonrow, #". That could be helpful if you also want to hide the quick launch and hide\display as well with Ctrl + G.

Hope you find this helpful :)

Sunday, April 1, 2012

Running Client Object Model on all Browsers

For those of you who developed some Client Object Model (Client OM) and tried to run the code in chrome or firefox, might have gotten the following error:
cannot read property 'get_current'
And if you tries to debug the code, you would have seen that SP.ClientContext was undefined.

This might be due to some of your code running trying to run without the "sp.js" file loaded to the page and with it the Client OM was not yet loaded to the page.

What you can do in this case is use the following format to ensure that the Client Object Model was loaded to the page:

ExecuteOrDelayUntilScriptLoaded(FunctionName, "sp.js");
function FunctionName()
{
    var context = new SP.ClientContext.get_current();
    // Code ...
}

You can also use the following format which removed the need for a specific function:
ExecuteOrDelayUntilScriptLoaded(function() {
    var context = new SP.ClientContext.get_current();
    // Code ...
}, "sp.js");

Thursday, March 29, 2012

The list cannot be displayed in Datasheet view

The following error occurred to me when trying to activate Datasheet view on my Internet Explorer.
I've seen many articles talking about this problem.

The problem description is as follows:
The list cannot be displayed in Datasheet view for one or more of the following reasons:
- A datasheet component compatible with Microsoft SharePoint Foundation is not installed.
- Your Web Browser does not support ActiveX controls.
- A component is not properly configured for 32-bit or 64-bit support.
Like in the following image:




In my case one did the trick was refreshing the SharePoint Designer installtion:
Control Panel > Programs and Features > Microsoft SharePoint Designer 2010 > Change:

Wait for the following screen to appear:
Choose Add or Remove Features and click Continue.
Under Office Tools select Microsoft Access Web Datasheet Component and under it select Run from My Computer.
(Even if the option is already active, reselect it)
And wait for the change to complete:

I got the problem in a Windows 7 machine, on a client that had Office 2003 installed (yes they still exist in some haunted locations...). Moreover, this station has a SharePoint Designer 2010 installed, and running the repair on that installation fixed my problem.

If this solution does not work, you have the following solution to help you:
In some cases the solution includes running the repair for Office Installation, like here:

Hope this helps you :)

Wednesday, March 28, 2012

PowerShell & SharePoint - Part 3


PowerShell & SharePoint - Working with SharePoint  Objects


This post is the second part of a series:
In this post:
  • Understanding SharePoint Inside PowerShell
  • Finding SharePoint Commands in PowerShell
  • Working with Site and Web objects
  • Getting a List from a Web Site
  • Updating List Items

Understanding SharePoint Inside PowerShell 
Loading PowerShell Console:
All Programs > Accessories > Windows PowerShell > Windows PowerShell

Loading SharePoint 2010 Management Shell:
All Programs > Microsoft SharePoint 2010 Products > SharePoint 2010 Management Shell

When we open a simple PowerShell Console we can't go ahead and use the SharePoint library and objects, but If we open the SharePoint 2010 Management Shell we will be able to interact with SharePoint from the get go. 

What is the difference?

The difference is quite simple, the SharePoint 2010 Management Shell uses a windows shortcut that calls a script into the PowerShell console, and that script contains a simple line:

Add-PSSnapin Microsoft.SharePoint.PowerShell

Which loads the objects and methods relevant for SharePoint in the PowerShell Console.

What is it good for?
Absolutely noth.. (just had the song stuck in my head, sorry :) )
Its very useful when connecting with PowerShell to remote servers, in which case the console (even if it is the SharePoint 2010 Management Shell) does not load the SharePoint library, so we have to load it with the Add-PSSnapin
  
Finding SharePoint Commands in PowerShell 
In PowerShell we have a very comfortable way to retrieve all commands which is Get-Command (aka gcm as alias)
So If we chose wrote the next line:

Get-Command -Noun SP*

Which will enlist all the commands in the PowerShell console that enable us interact with SharePoint.

Working with Site and Web objects 
For those of you who have developed in the past for SharePoint you might be familiar with many of the object, methods and properties.

The basic cmdlets for interacting with SharePoint are:
Get-SPSite
Get-SPWeb

and we can use them in the following ways:

# Get all site collections in the farm
Get-SPSite

# Get all site collections (without limit, you would only get the first 15 or so site collections
Get-SPSite -Limit ALL

# Get the site collection in the url http://siteurl
Get-SPSite "http://siteurl"

# Get the web site in the url http://weburl
Get-SPWeb "http://weburl"

# Get all the web sites in all the site collections
Get-SPSite | Get-SPWeb

This examples shows some basic functionality uses.
The interesting one is last one, because you get all the site collections and then pipe the resulting object to the command Get-SPWeb which knows to take a collection of site collections (or just a single one) and for each one return all the child web sites.


The following examples shows how to work with the resulting objects:
# This exmaple shows how to enlist the master pages 
Get-SPSite http://devsrv | Get-SPWeb | select title, masterurl

Which will return a table containing the title and master url of each master page in the site collection.

Getting a List from a Web SiteIn order to get a list from the web site we would need to interact with the SPWeb object. Because we don't have a cmdlet for retrieving lists, we will use the object module in one of the following ways to get the list "Share Documents" from the SPWeb object:

# Option 1 for getting the list from an SPWeb object
(Get-SPWeb "http://weburl").Lists["Shared Documents"]

# Option 2 for getting the list from an SPWeb object
$web = Get-SPWeb "http://weburl"
$web.Lists["Shared Documents"]

# In both cases we can store the returned list in a variable
$list = (Get-SPWeb "http://weburl").Lists["Shared Documents"]

Updating List Items
One of the trickier part in working with SharePoint objects is the list item, the reason is that the PowerShell Console does not now to address it as a SPListItem object, for that reason we need to case the object into an SPListItem object and only then can we use its methods and properties. 

This is a small example of using the object:

# In both cases we can store the returned list in a variable
$list = (Get-SPWeb "http://weburl").Lists["Shared Documents"]
$item = $list.GetItemByID(1)
$listItem = [Microsoft.SharePoint.SPListItem]$item
$listItem["FieldName"] = "New Value"
$listItem.Update()

This is a fairly simple example, you can look at the following short article to see a more comprehensive example of updating a list item:
http://morshemesh.blogspot.com/2012/03/turning-c-code-to-powershell.html 

You can keep following and checking further more comprehensive topics of SharePoint & PowerShell in the following link in my blog:
http://morshemesh.blogspot.com/search/label/PowerShell 

I hope you enjoyed this series :)

Sunday, March 18, 2012

Turning C# Code To PowerShell

Hello Everybody,
In this post I've decided to tell you how to create PowerShell Code from code you find in C#, writed in Visual Studio 2010. The reason is that in many cases we might find exactly what we want to achieve in C# but we need the code snippet in a PowerShell script for various reasons.

It's pretty simple once you get the hang of things. Lets take the following code section:

using(var site = new SPSite("SiteUrl"))
using(var web = new site.OpenWeb("WebUrl"))
{
    SPList list = web.Lists["ListName"];
    
    SPQuery query = new SPQuery();
    query.Query = @"<Where>
                    <Eq>
                       <FieldRef title""="">
                       <Value text""="" type="">Some Title</Value>
                    </FieldRef>
                    </Eq>
                  </Where>";

    SPListItemCollection items = list.GetItems(query);
    
    foreach (SPListItem item in items)
    {
        item["FieldName"] = "Value"; // Comment
        item.Update();
    }
}
This code sample challenges us to perform the following translations:

  1. Using variables
  2. Creating a new SPWeb object
  3. Create an SPQuery object
  4. Add a string with line feeds (newline)
  5. Perform a foreach on the returned results
  6. Update the list item
So here are the steps broken down:

1. Using Variables
In PowerShell we can only use variables if we use the $ sign, but we don't need to declare them, so variabled list web, list will be addressed by $web, $list.


2. Creating a new SPWeb object
For those of you who know the SPWeb object, knows that it opens a database connection on creation (a COM object in other words). For this reason we use the using section. 
In PowerShell we don't have the using key word, and in most cases we don't really need to dispose the SPWeb object, since it will be disposed (or removed from memory) once you close the PowerShell Console. You should keep in mind that if you open multiple SPWeb objects (or SPSite, SPWebApplication) which can happen in loops, this might dramatically lower that performance of the script if objects are not disposed properly.
Moreover, in PowerShell we can directly create an SPWeb object, without primarily creating an SPSite object. 
This is the code we will use:

$web = Get-SPWeb "WebUrl"
...
$web.dispose()

3. Create an SPQuery object
To create an SPQuery object, we can use the New-Object cmdlet in the following way instead of using the new command in C#:

$query = New-Object Microsoft.SharePoint.SPQuery

4. Add a string with line feeds (newline)
In C# we have the "\" for special characters, which is replaced by "`" in PowerShell (on top of the Tab button on most key boards), which can also be used for new lines in strings. Moreover, instead of double quotation marks <""> we will use the combination of <`">:

$query.Query = "<Where> `
    <Eq> `
        <FieldRef name=`"Title`"> `
            <Value type=`"Text`">Some Title</Value> `
        </FieldRef> `
    </Eq> `
</Where>"

5. Perform a foreach on the returned results
We have more than one way to perform a foreach on an object array in PowerShell, In this example I will show the one most comfortable to use in code translations:

foreach ($item in $items)
{
    ...
}
Notice, that I use the variables $item and $items, and that I don't declare $item with SPListItem.

6. Update the list item
Now, the lest part is tricky but only because this is one of the only places where the connection between PowerShell and .Net Framework was done only halfway. What do I mean? in most cases you could just go on and use $item like an SPListItem object with $item["FieldName"], ... , $item.Update();. The problem is that PowerShell still doesn't know in this point that we are using an SPListItem object, so in this particular case (and a handful of others) we are going to use a casting like this:

$listItem = [Microsoft.SharePoint.SPListItem]$item

And now we are all set up for the final script:
$web = Get-SPWeb "WebUrl"

$list = $web.Lists["ListName"]
$query = New-Object Microsoft.SharePoint.SPQuery
$query.Query = "<Where> `
    <Eq> `
        <FieldRef name=`"Title`"> `
            <Value type=`"Text`">Some Title</Value> `
        </FieldRef> `
    </Eq> `
</Where>"

$items = $list.GetItems($query)

foreach ($item in $items)
{
    $listItem = [Microsoft.SharePoint.SPListItem]$item
    $listItem["FieldName"] = "New Value" # Comment
    $listItem.Update()
}

$web.dispose()

One more thing, you can add ";" at the end of each command, but PowerShell does not require such endings to commands.

So a few rules to kip in mind:

  1. Dispose of your SPWeb and SPSite objects
  2. Remove variable declarations (instead use direct assignment)
  3. Create and use variables with a preceding <$> sign.
  4. Use <`> instead of <\>, in most cases it will be the right choice
  5. When you can't call a method, use casting
  6. When you create new objects, call New-Object
  7. For calling static methods you can call [Namespace.ClassName]::StaticMethod(), I haven't shown this example but it can be useful in quite a few cases.
  8. Comment text with the <#> sign.
  9. And, in case you didn't notice from this post, PowerShell commands (or cmdlets) are case insensitive, meaning, you can call $web.dispose() as well as $web.Dispose(), or $listItem.update() as well as $listItem.Update().
And don't forget to enjoy PowerShell :)

Tuesday, March 6, 2012

Web Parts - Out Of The Box Part 5


This article is the first in a series of articles.
The other articles are:

  1. Web Parts - Out Of The Box Part 1
  2. Web Parts - Out Of The Box Part 2
  3. Web Parts - Out Of The Box Part 3
  4. Web Parts - Out Of The Box Part 4
  5. Web Parts - Out Of The Box Part 5 Current Article
Web Parts - Advanced Capabilities
This article will talk about some of the more advances capabilities inherent in every web part, and which come as part of the web part base features.

 I will talk about the following topics:

  • Appearance
  • Layout
  • Advanced


Appearance

This section in the tool pane of every web part enables editing some general appearance of the web part:
  • Title - the title that will appear above the web part
  • Height\Width - Set a constant Height and\or Width to your web part
  • Chrome State - Determines whether the web part will appear as collapsed or expanded (normal) 
  • Chrome Type - Choosing to display all\some\none of: Title\Border.
Layout
Enables changing the layout and location of the web part in the document.

Advanced
Here we can find some really interesting options:
  • Allow Minimize: Allow the users to minimize the web part (collapse it)
  • Allow Close: Allow removing the web part from the page (but it will still be available in closed web parts)
  • Allow Hide: Allow hiding the web part from the page
  • Allow Zone Change: Allow moving the web part between zoned (only relevant for pages with web part zones)
  • Allow Connections: Allow this web part to receive or send data from\to other web parts in the site.
  • Allow Editing in Personal View - Allow users to customize this web part to in a personal customization.
  • Export Mode - What kind of data will be exported when exporting this web part.
  • Title Url - Enables displaying the Title as a link and this will be the link to show.
  • Catalog Item Image URL - The icon to display in the web part gallery
  • Title Icon Image URL - The icon to display next to the title of the web part.
  • Target Audiences - Specify a group of people (SharePoint Group) that will be able to see this web part (Notice that this is not a permission for the data inside this web part)
I hope this collection of articles was helpful for you, and that you keep finding articles of interest in my blog :)

This is a nice example of what you can do Out Of The Box:


Have fun with web part!

Web Parts - Out Of The Box Part 4



This article is the fourth in a series of articles.
The other articles are:



Extras
In this article I will cover some of the OOTB web parts that interest me and might be relevant for you.


These web parts are:

  • Social Collaboration - Note Board
  • Business Data - Chart
  • Search - People Search Box

Note Board
You can find the Note Board web part under the Social Collaboration group (please note that in order to see this web part you farm needs to have User Profile services activated and running. A sure sign for that is having My Site or be able to see a User Profile of yourself or another person in your organization).

The Note Board web part enables adding talk back functionality on your page.
This is an example of me using this web part (please forgive the typo :-)  ):

Chart
The Chart web part is quite a nice a addition to the OOTB web part collection. You can find it under Business Data category when trying to add a new web part to your page.
This web part is also a quick way to impress your boss with some visual display of important data :-)

Before adding this web part to the page i would like to add a list web part with some data I entered.
Notice: Prior to this lab I have created a custom list containing the following fields:
  • Department (Renamed from Title)
  • Month (Single line of text)
  • Income (Number)
You can create your own set of data.

After adding it you will see a small graph and the following toolbar:

This web part is a very special web part since it enables us to start two wizards in order to define it.
We will start with the first wizard for Data & Appearance:
In this screen we will first pick Connect Chart To Data to connect to a data source.

In the following screen we can select what source type we would like to connect to.
I chose to connect to another web part since I wont the two elements to correspond to each other on the page.

Next:
We choose the web part we added to the page before adding the Chart web part.

Next:
This screen enables us to choose the from chart templates to display.
If you chose the web part option you would have only one choice.

Next:
In this wizard step we associate our chart with data from the other web part.
I chose to display the Income in the X axis, Month in the Y axis and to group by title (department). please notice that group by will not group together and sum the results but will color the various values in different and distinct colors.

The result is:

And the nice correspondence between the two web parts is when you filter the Sales web part, the result is:
If you click on the Data & Appearance and then on Customize Your Chart:
You will get the opportunity to choose between 2D and 3D graphs and change the type of graph to Spatter, lines, pie etc.

People Search Box
The people search box is a simple search box that enables you to add people search functionality to any page in your site, and it will function like the people search page in you search site.
You can find this web part under Search category.

You can move on to the next and final article in the series to learn about Advanced Web Part Functionality: