Tuesday, March 29, 2011

Enabling a Button on the Ribbon Based on Selection

Enabling a Button on the Ribbon Based on Selection

A lot of people have asked me how to create a button which enables if and only if a single item is selected. This isn’t something we have out of the box, but the code to get this functionality is pretty simple. I’m going to assume that you’re generally familiar with SharePoint, CustomActions, and customizing the Ribbon – if that’s not the case, you’d probably be better off researching those things before delving into this.
Basically, the enabling behavior all boils down to the following few lines of code:

EnabledScript="javascript:function singleEnable() {   var items =
   
SP.ListOperation.Selection.getSelectedItems();   var ci = CountDictionary(items);   return (ci == 1); } singleEnable();"

What this does is query to get the dictionary of selected items, and if the size of the dictionary is 1 it returns true (enable), otherwise it will return false (disable). Technically, I should have used Script on Demand to call into the SP.* namespace, but since I’m calling this from the Ribbon I have a high confidence that SP.js has been loaded already.

With nothing selected:

image

With one item selected:

image

Clicking the button:

image

And with more than one item selected:

image

You could also change this to enable only if no items were selected, or if any number of items were selected. The way to make those kinds of changes should be relatively self-explanatory.
The full CustomAction code for a sample Ribbon button which enables when one item is selected is at the end of this post. The code assumes the following:
  1. You want to add this button to the New group on the Documents tab. If you want to add the button to another location, you should change the Location attribute of the CommandUIDefinition element (as well as change any appropriate attributes in the Button element, such as Id and Sequence, to match the new location).
  2. You have an icon image at LAYOUTS/SharePointProject1/DemoButton.jpg. If that’s not the case, you should either put an icon at that location or change the Image32x32 attribute to a valid icon path.

CustomAction code:

<CustomAction   Id="EnableSingleSelectButton"   Location="CommandUI.Ribbon" >   <CommandUIExtension>     <CommandUIDefinitions>
     
<CommandUIDefinition   Location="Ribbon.Documents.New.Controls._children">   <Button Id="Ribbon.Documents.New.EnableSingleSelectButton"           Alt="Button enabled on single selection"           Sequence="35"           LabelText="Single Select"
 
Image32by32="/_layouts/SharePointProject1/DemoButton.png"           Command="SingleSelectButton"           TemplateAlias="o1" />       </CommandUIDefinition>     </CommandUIDefinitions>     <CommandUIHandlers>       <CommandUIHandler           Command="SingleSelectButton"           CommandAction="javascript:alert('There is only one thing selected!');"           EnabledScript="javascript:function singleEnable()
          {
            var items = SP.ListOperation.Selection.getSelectedItems();             var ci = CountDictionary(items);             return (ci == 1);           }           singleEnable();" />     </CommandUIHandlers>   </CommandUIExtension> </CustomAction>

Monday, March 14, 2011

How To Hide Ribbon From Users Without Edit Page Privilege

 A way to remove or hide the ribbon area from user with lease privilege, and here is how:
1)      Open your SharePoint master page
2)      Locate this line:<div id="s4-ribbonrow" class="s4-pr s4-ribbonrowhidetitle">
3)      Change it to:<div id="s4-ribbonrow" class="s4-pr s4-ribbonrowhidetitle" style="display:none">
4)      Now find the end of the “s4-ribbonrow” tag and add following block right after it:<Sharepoint:SPSecurityTrimmedControl ID="SPSecurityTrimmedControl2" runat="server" PermissionsString="AddAndCustomizePages">    <script type="text/javascript">        document.getElementById("s4-ribbonrow").style.display = "block";
    </script>
</
Sharepoint:SPSecurityTrimmedControl>
5)      Save the new master page and publish it.
Learn more about SPSecurityTrimmedControl

Sunday, March 6, 2011

How to Remove Corrupted SharePoint Sites – Preparing for SharePoint 2010 Upgrade

 
SP2 had a number of enhancements designed around making it easier to upgrade to SharePoint 2010.  One such new feature that wasn’t popularized is your ability to find and remove corrupted, broken sites known as orphans.
As I’ve mentioned in the past, with SharePoint being split across multiple databases, it is quite possible that a site could be in either the content database OR the config database.
With service pack 2 there’s a new way to find orphaned sites.  In addition to running STSADM –o PreUpgradeCheck, one of my favorite tools along with TEST-SPContentDatabase with SharePoint 2010 you can identify these messed up corrupted sites.
You’ll run enumallwebs (STSADM reference on TechNet) to identify the orphaned sites, and use deletesite (STSADM reference on TechNet) to remove them.  Note this command is available in SP2, and was enhanced in the post SP2 October Cumulative update.  You really should consider that October update as the most significant release with upgrades since SP2, but also extremely relevant in getting ready for upgrade to SharePoint 2010.  Look for the new –force across a few different commands.  You don’t have to use the –force the first time around.  Use it when things error out due to corruption.
 

Identifying Site Collections and Sites

Both Identify the sites missing from the Site Map and identify the GUID so it can be deleted.
STSADM –o EnumAllWebs
Syntax
stsadm -o enumallwebs
   -databasename <database name>
   [-databaseserver <database server name>]
With STSADM –o EnumAllWebs you can get a list of all of the sites.  It may not seem very readable, but throw it into Excel or your favorite text editor or XML editor and clean it up.  Once you’ve got it in the editor you’re going to look at the data where InSiteMap="False".  Essentially what you’re looking at is a problem.  If it’s not in the site map then it doesn’t think it really fully exists.

Delete Corrupted Sites

Syntax from TechNet
For deleting a live site collection:
stsadm -o deletesite
   -url <URL name>
   [-deleteadaccounts {True | False}]
   [-gradualdelete]
For deleting a orphaned site collection:
   -force
   [-gradualdelete]
   -siteid <site ID> (ID is listed in an output from EnumAllWebs)
   -databasename <database name>
   -databaseserver <database server name>

For Deleting Corruption
“The databaserepair operation can detect and repair database corruption for only the following types of orphaned items in a content database:
  • A Windows SharePoint Services Web site that does not have a parent Windows SharePoint Services Web site
  • A subweb that does not have a parent Windows SharePoint Services Web site
  • A list that does not have a parent Windows SharePoint Services Web site
  • A document that does not have a parent document library
  • A list item that does not have a parent list
  • A Web page that does not have a parent Windows SharePoint Services Web site”
Syntax
stsadm -o DatabaseRepair [-deletecorruption]
stsadm -o databaserepair
   -url <url name>
   -databasename <database name>
   [-deletecorruption]

Delete Corrupted Webs

Syntax from TechNet
For deleting a live site within a site collection:
stsadm -o deleteweb
   -url <URL name>
For deleting a site within an orphaned site collection or an orphaned site within a site collection:
   -force
   -webid <Web ID>  (ID Comes from EnumAllWebs)
   -databasename <database name>
   -databaseserver <database server name>

The real useful feature is the new –force parameter.  Essentially now you have the ability to add the –force when adding the URL of one of these orphaned sites.  Before you’d simply get an error if you were trying to delete one of these sites.  If you plan to use the –force parameter with your EnumAllWebs command you will need to provide the GUID which is the site id or web id.  By simply looking at the XML output you can tell wether you need to run web or site command.

<Sites Count="2">
  <Site Id="e2a23r5h-83c9-43t6-8wcf-3fesasefdsd234"
OwnerLogin="Domain\username" InSiteMap="False"> 
    <Webs Count="1">
      <Web Id="0ae3237b-b349-4693-bd67-dsefcsabb36" 
Url="/sites/site_name" LanguageId="1033" TemplateName="STS#3" TemplateId="1" />
    </Webs>
  </Site>
  <Site Id="fsdf32c4b8-79d9-32f6-87bf-4acreadcr3623"
 OwnerLogin="Domain\username" InSiteMap="True">
    <Webs Count="1">
      <Web Id="234c8e7b-c456-4693-bd67-efdegd3bf466"
 Url="/" LanguageId="1033" TemplateName="STS#0" TemplateId="1" />
    </Webs>
  </Site>
</Sites>

If you find the results from enumallwebs too overwhelming you can trim down what you’re looking at to a specific database.  You can pass in the –database parameter and provide a specific database.  For example: stsadm -o enumallwebs -databasename sharepoint_content_db
DON’T FORGET TO BACKUP YOUR DATABASES FIRST!

Here’s the KB that refers to the old ways of cleaning up orphaned sites
Repair content databases in Windows SharePoint Services http://support.microsoft.com/kb/918744

If anyone ever tells you to simply disconnect and reconnect your databases, you need to be very serious about what that means.  It sounds very simple, and in simple environments that might be ok.  In other environments you’ll find there’s a lot of layers of configuration around databases and by simply disconnecting and reconnecting you’ll lose the association with alerts and other services, essentially much of the configuration in the SSP that relates to those sites loses it’s way. 
If you’re seeing a lot of corruption you should refer to this post on how SharePoint site corruption is created to see if you can follow better practices to avoid creating corruption.

I got this solution form this site.