Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

Written by MMMan. Posted in Uncategorized

I’ve run into problems at times when trying to activate the SharePoint site feature “SharePoint Server Publishing”. In the instance below, essentially the problem boiled down to the fact that there was already a “PublishingImages” library. As it turns out, this is simply a library by the name of “Images”. To resolve this, simply rename the library to some other name, then try to reactivate the feature.

Rename the “Images” Library

  1. Start by going into the Site Contents listing

    072214 0450 UnabletoAct1 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

  2. In the list, look for an “Images” library.

    072214 0450 UnabletoAct2 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

  3. If you have an existing Images library, we’re going to need to rename the library. If you have existing images using the files in the library, you can move them into the new library (after it’s created in a section below), or you can update your references to point at the new name (if necessary).
  4. In the library, go into the “Library” tab and choose “Library Settings”

    072214 0450 UnabletoAct3 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

  5. In the settings, choose “List name, description and navigation”

    072214 0450 UnabletoAct4 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

  6. Rename the library to something other than Images (such as ImagesOld)

    -072214 0450 UnabletoAct5 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

Now Activate the Site Feature

  1. Next, return to Site Settings and under “Site Actions” choose “Manage site features”

    072214 0450 UnabletoAct6 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

  2. Scroll down and find the feature “SharePoint Server Publishing” and choose “Activate”

    072214 0450 UnabletoAct7 Unable to Activate Site Feature “SharePoint Server Publishing” when PublishingImages Library Already Exists

    Important note: There may be NO UI responsiveness for up to a minute. DO NOT click the button again, just wait for the process to complete in the background.

    Additional note: This is where the new “Images” library is created, so if you have images from earlier which need a new library to live, they can be moved into this library if necessary (from the ImagesOld library).

Checking which Delegate Controls are activated on your site

Written by MMMan. Posted in Uncategorized

I recently had the need to determine which delegate controls were activated on my site collection. Unfortunately I quickly discovered there was no easy way to do this in the SharePoint GUI. As such, I went searching on the Google machine, and I came across the article below. It has a great, concise overview of the problem, along with a fully flushed out PowerShell script to help you determine what you need to know.

Enjoy the post, I know I did. Many thanks to Waldek Mastykarz for writing it.

http://blog.mastykarz.nl/checking-which-delegate-controls-activated-site/

Resolving Issue “Item is no longer available. It may have been deleted by another user. Click ‘OK’ to refresh the page.” with XSL Link

Written by MMMan. Posted in SharePoint

I recently came across an issue where a client of ours was using the “XSL Link” in the Miscellaneous section of a list view web part. What was happening was when the user clicked on the context menu of an item in the list, they would receive the following error message.

Item is no longer available. It may have been deleted by another user. Click ‘OK’ to refresh the page.

It turns out that the client was using a local site collection asset in the XSL Link. In other words, the path to the file was similar to “/SiteAssets/XSL/no-items.xsl“. Doing this can cause the error above.

To resolve this, you need to install the file on the SharePoint web server(s) in the LAYOUTS directory either in a WSP solution, or directly in the farm under the following;

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS (for SharePoint 2010)

    OR C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS (for SharePoint 2013)

    Such as this below:

    071014 0444 ResolvingIs1 Resolving Issue “Item is no longer available. It may have been deleted by another user. Click OK to refresh the page.” with XSL Link

Then you’ll instead refer to the file more like this in the XSL Link instead “/_layouts/no-items.xsl“.

To assign the XSL Link on a list view web part, edit the web part.

071014 0444 ResolvingIs2 Resolving Issue “Item is no longer available. It may have been deleted by another user. Click OK to refresh the page.” with XSL Link

Then set the XSL Link in the Miscellaneous section. Be sure to use the technique above and put the file in the farm so you can set the reference to the layouts directory (demonstrated below).

071014 0444 ResolvingIs3 Resolving Issue “Item is no longer available. It may have been deleted by another user. Click OK to refresh the page.” with XSL Link

Hiding Empty SharePoint Web Parts Using JavaScript/jQuery on a Dashboard Page

Written by MMMan. Posted in JavaScript, Microsoft, Office 365, SharePoint

Note: The technique described below is designed for SharePoint 2013.  It could be adapted to 2010, but it’s not likely to work in 2010 with a simple copy/paste.

Note 2: This also should work just fine in Office 365, so get ready to knock some socks off.

In SharePoint 2013 we at itgroove have a lot of dashboards that we use for various purposes (the consultant dashboard, the GM dashboard, the president’s dashboard, and about 20 or so more) and one of the problems we always had was trying to jam more relevant content on to each dashboard, while simultaneously trying to reclaim as much space as possible (show the user what they need to see).

Enter the solution below.  It’s a piece of code designed to hide empty web parts on a SharePoint dashboard, if the contents of that web part is empty.  The reason this code works is that many of our web parts are simply list views of content already in SharePoint.  This code is mainly only going to hide empty list view web parts – so if you have a dashboard with other empty web parts (whatever those may be), you may be out of luck, or you may be able to adapt it somehow, but this is all you get from me for free.  wlEmoticon winkingsmile Hiding Empty SharePoint Web Parts Using JavaScript/jQuery on a Dashboard Page

Note: We’re already including a jQuery library in our masterpage, and as such, I haven’t included a reference to bring in the jQuery library.  Essentially, if you don’t already have jQuery elsewhere on the page (or in the masterpage like I do), you can include the following line above the code below.

/* If you don’t have jQuery already included, use this */
<script type=”text/javascript” src=”http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js”></script>

Essentially what the code below is doing is as follows.  The waitForSPReady method is essentially sitting in a loop waiting for SharePoint to be ready to perform the action in the main body of code.  If the method “SP.ClientContext.get_current” isn’t yet ready, SharePoint isn’t ready, so it will wait another 100ms and try again.  Once SharePoint is ready, cleanupEmptyWebParts is called, which gathers a collection of all the web parts on the page that have the CSS class “ms-list-emptyText-compact”.  It then iterates over that collection and for each valid item, it hides the web part if it successfully finds a match for the CSS class “ms-list-emptyText-compact” (you can never be too sure – that’s why there’s a bunch of code to test for it’s presence properly, and traverse around the DOM to find the right thing to hide).

Note: The variable “itgDebugEnabled” allows you to manually turn the functionality on or off, by setting this in a JavaScript variable somewhere in the page (set the variable to “true” to stop the code from processing).  If you want to set the variable, either you can set it in this code (somewhere earlier/outside the method) or it can be set in any other included file / script block on the page.

To add this code to a web part page, just add a “Script Editor” web part to the page, and include the code in there.

Note: The code below should work in all major (modern) browsers that are supported by SharePoint.  It’s been tested on all of the latest major browser versions (as of the publishing of this article).  I do not know how well it will work on significantly older browsers (like IE 7/8/9).

The code:

<script type="text/javascript">
 $(document).ready(function(){
     setTimeout(waitForSPReady, 100);
 });

function waitForSPReady()
 {
     if (typeof SP == "object" && typeof SP.ClientContext == "function" && typeof SP.ClientContext.get_current == "function")
     {
         cleanupEmptyWebParts();
     }
     else
     {
         setTimeout(waitForSPReady, 100);
     }
 }

function cleanupEmptyWebParts()
 {
     if (typeof itgDebugEnabled != "undefined" && itgDebugEnabled == true)
     {
         return;
     }
     var outerEltClass = "ms-webpartzone-cell";
     var eltList = $(".ms-list-emptyText-compact");
     var outermostID = "_invisibleIfEmpty";

    if (eltList.size() > 0)
     {
         var iter = null;
         var curItem = null;
         for (iter = 0; iter < eltList.size(); iter++)
         {
             curItem = eltList[iter];
             if (curItem.id == outermostID)
             {
                 continue;
             }
             else
             {
                 while (curItem.id != outermostID)
                 {
                     var foundItem = false;
                     var cIter = -1;
                     var maxIter = curItem.classList.length;
                     if (maxIter > 0)
                     {
                         do
                         {
                             cIter++;
                             if (curItem.classList[cIter] == outerEltClass)
                             {
                                 foundItem = true;
                                 break;
                             }
                         }
                         while (curItem.classList[cIter] != outerEltClass && cIter < (maxIter - 1))
                         if (foundItem == true)
                         {
                             $(curItem).css("display", "none");
                             break;
                         }
                     }
                     curItem = curItem.parentNode;
                 }
             }
         }
     }
 }
 </script>

Before:
(Note the 5 empty list view web parts + my tasks)

image thumb3 Hiding Empty SharePoint Web Parts Using JavaScript/jQuery on a Dashboard Page

After:
(Now only my tasks are left – I’d show you all the empty whitespace on the screen, but there’s not a lot of point wlEmoticon smile Hiding Empty SharePoint Web Parts Using JavaScript/jQuery on a Dashboard Page)

image thumb4 Hiding Empty SharePoint Web Parts Using JavaScript/jQuery on a Dashboard Page

Hopefully you find this as useful as I did.

Sending an Email to a SharePoint Group Using Nintex

Written by MMMan. Posted in Nintex, SharePoint

What I was looking to determine was what would happen if I sent an email to a SharePoint group, as opposed to explicitly defining a set of users in a workflow variable.  Up until now, I’d never really known what would happen when sending email to a SharePoint group, so here’s what I found.

As you can see (included below) is an email sent by SharePoint to the “SharePoint Group” “Colins Special Group”.  I created this workflow using Nintex Workflow 2013, but have no reason to think it wouldn’t work in 2010 as well.

The list of users in my group (seen below) included myself and my colleague Matt.

image thumb Sending an Email to a SharePoint Group Using Nintex

In the email, you can see the recipients list matches exactly with the group membership (myself and Matt).  I can confirm that both of us received a copy of the email.

Note that the workflow is a simple one step workflow, it just sends a notification email.

image thumb1 Sending an Email to a SharePoint Group Using Nintex


Email Sent to Each Recipient:

From: [sharepoint server] @ [domain].[com]
Sent: June 19, 2014 3:16 PM
To: Colin Phillips; Matt Longpre
Subject: Sweet!  It worked!

*** Email Body Would Go Here ***


One thing to note, in the Nintex Workflow action “Send notification”, there is a checkbox when sending emails that’s supposed to prevent other people from knowing who else was notified by the same notification (seen below “Send individually addressed notifications”).  Unfortunately, you can see in the email (above), the entire list of users was included in the “To” field, allowing me to know who else was notified at the same time.  If this is an issue for you, then you’d likely want to use an explicit list of users (defined in a workflow variable within the workflow) instead of a SharePoint group.

image thumb2 Sending an Email to a SharePoint Group Using Nintex

Note: To create a SharePoint Group, you go into “People and Groups” in the site settings, create your group, and set what permissions that group will have.  Finally, add your users to that group, and you’re off and running.

Hopefully this can help others with the challenge of understanding how SharePoint groups and Nintex notifications work.

Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

Written by MMMan. Posted in PowerShell, SharePoint

If you’ve deleted a site collection (anytime as of or after SP1 in SharePoint 2010 – note prior to 2010 SP1, you’re out of luck), and you want to recover the site collection, it’s actually quite simple.

Note that in Office 365 simply go into the admin interface for SharePoint, in the section where you manage your site collections.  Look for the recycle bin icon on the ribbon, in there you can you just restore your deleted site.

Let’s be daring and delete my local mysite. 

SNAGHTML25e6559b4 thumb Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

image thumb Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

Oh my goodness!  Whatever have I done!? 

Well, now’s the time to employ the good old PowerShell.  Start by launching an Admin PowerShell window and running the following:

Get-SPDeletedSite

This will return a list of all the deleted site collections.

image thumb1 Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

What we’re looking for is the SiteId, which we’ll use in the next step.

Restore-SPDeletedSite –Identity <siteId>

SNAGHTML25f8ccf6 thumb Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

You’ll be prompted for confirmation.  Simply say yes, or just accept the default.

Note: You wont receive any confirmation, but if you simply go to your site, it’ll be recovered.

image thumb2 Restore a Deleted Site Collection in SharePoint 2010 SP1+ and SharePoint 2013

w00t!

PSConfig Fails with Missing / Required Error Message After Applying CU or Service Pack in SharePoint 2010

Written by MMMan. Posted in PowerShell, SharePoint

The following blog post saved our farm.  Well, maybe not quite that dramatic, but it certainly saved me a lot of time.  Essentially, the only thing I had to do was run the suggested PowerShell, and everything worked perfectly afterwards.

“Try running the command Get-SPProduct –local on the server that says it’s missing the required patch.”

http://blogs.technet.com/b/speschka/archive/2011/06/29/psconfig-fails-with-missing-required-error-message-after-applying-cu-or-service-pack-in-sharepoint-2010.aspx

An Alternative Photo Rotator Solution

Written by MMMan. Posted in JavaScript, SharePoint

A customer of ours had an issue with the out of the box photo rotator in SharePoint – every few minutes it kept prompting them for credentials.  After some inspection, I noticed that pretty much every rotator solution would always change the image by swapping between two <img> elements, and changing the URL of the one not currently in focus.  As this was ultimately causing the browser to fetch new content every few seconds, I decided to write my own rotator which instead does a one time pull of all the images, and iterates between the collection.

Many thanks to Bill Simser for much of the code for querying the lists in this article here.

First off, get a copy of a jQuery library and store it somewhere on your site.  Next, create a picture library, and name it “Rotator Images”. 

After you’ve got those in place, put this code into a content editor (using edit HTML source), and your rotator should come alive.

Here’s the code, enjoy!

<div id="RotatorCont"></div>
<style type="text/css">
.pictureWrapperDiv
{
	margin: 0px;
	padding: 0px;
	border: 0px;
}
.pictureGallery
{
	margin: 0px;
	padding: 0px;
	border: 0px;
}
</style>

<script type="text/javascript" src="/Style%20Library/Branding/Scripts/jQuery-1.7.1.js"></script>
<script type="text/javascript">

//Globals for # of secs between images, max width and height, and the name of the picture library (must be local to this web site)
//You can modify these as necessary
var itgLoadTimeSecs = 8;
var itgImgHeight = 296;
var itgImgWidth = 390;
var itgRotatorLibraryTitle = "Rotator Images";

//Globals for internal use only (don't change these)
var itgImgRotCount = 0;
var itgImgRotIter = 0;
var picid = "itgDynaImg";
var itgLoadTime = itgLoadTimeSecs * 1000;

$(document).ready(function(){
    //start your engines
	pageonload();
	
	//Set a slight delay before kicking off the query (just for good measure)
	setTimeout(loadSharePointPictures, 250);
});

function pageonload()
{
	var rota = $("#RotatorCont");
	rota.css("display", "inline-block");
}

function loadSharePointPictures()
{
	//fetch the list of items using the client object model
	var context = new SP.ClientContext.get_current();

	//get the current website
	var web = context.get_web();

	//get the pictures list
	var list = web.get_lists().getByTitle(itgRotatorLibraryTitle);

	//create the query to get all items
	var query = SP.CamlQuery.createAllItemsQuery();

	//get all items from the query
	pictures = list.getItems(query);

	//load the context
	context.load(pictures, 'Include(FileLeafRef,FileDirRef)');

	//execute the query in async mode
	context.executeQueryAsync(
		Function.createDelegate(this, this.success), 
		Function.createDelegate(this, this.failed)
	);
}

function success(sender, args)
{
    pictureArray = new Array();
    var pictureCount = 0;
	
	//pull the details about each image (directory and filename) out of the result
    var enumerator = this.pictures.getEnumerator();
    while(enumerator.moveNext())
	{
        var currentItem = enumerator.get_current();
        var filename = currentItem.get_item('FileLeafRef');
        var dir = currentItem.get_item('FileDirRef');
        filename = dir + '/' + filename;
        pictureArray[pictureCount++] = filename;
    }
    var newHtml = '';
	
	//set the first image to display
	var itgdispval = "block";
	
	//iterate through the result and create HTML code (img with div wrapper) for each picture
    for(var i = 0; i < this.pictureArray.length; i++)
	{
		if (i > 0)
		{
			//set all the additional images to hidden
			itgdispval = "none";
		}
        newHtml += '<div id="' + picid + i.toString() + '" class="pictureWrapperDiv" style="height: ' + itgImgHeight + 'px; max-height: ' + itgImgHeight + 'px; width: ' + itgImgWidth + 'px; max-width: ' + itgImgWidth + 'px; display: ' + itgdispval + ';"><img class="pictureGallery" src="';
        newHtml += this.pictureArray[i];
        newHtml += '" style="max-height: ' + itgImgHeight + 'px; max-width: ' + itgImgWidth + 'px;"/></div>';
    }
	//store the number of images
	itgImgRotCount = i;
	
	//start the iterator
	itgImgRotIter++;

	//assign the HTML to the rotator container
    $('#RotatorCont').html(newHtml);
	
	//start the rotator
	setTimeout(itgRotateImg, itgLoadTime);
}

function failed(sender, args)
{
	//alert("Failure: [" + sender + "] / [" + args + "]");
}

function itgRotateImg()
{
	var dynapicid = picid + itgImgRotIter.toString();
	var dynalast = 0;
	if ((itgImgRotCount > 0) && (itgImgRotIter == 0))
	{
		dynalast = itgImgRotCount - 1;
	}
	else
	{
		dynalast = itgImgRotIter - 1;
	}
	var dynapicidlast = picid + dynalast.toString();

	//hide the last image to be displayed
	$('#' + dynapicidlast).css("display", "none");
	
	//show (fade in) the next image
	$('#' + dynapicid).fadeIn(400);
	if ((itgImgRotIter + 1) < itgImgRotCount)
	{
		itgImgRotIter++;
	}
	else
	{
		itgImgRotIter = 0;
	}
	setTimeout(itgRotateImg, itgLoadTime);
}
</script> 

10 amazingly stupid things the ‘experts’ will try to tell you about Microsoft

Written by MMMan. Posted in Microsoft

Some experts are so bad at being experts, that calling some people an “expert” is like calling my dog a genius because he can find food on the floor.  Good dog.  So, needless to say, these statements below are often made by people with something to gain by spreading these “expert opinions” (slimy sales people for the competition perhaps???). 

http://www.zdnet.com/10-amazingly-stupid-things-the-experts-will-try-to-tell-you-about-microsoft-7000026827/