Keep Results Empty Until User Searches

Scenario:

When you navigate to a custom search page, the Search Results web part is already populated even though you haven’t searched for anything yet.

You want the Search Results web part to remain empty until a user searches for something.

Solution:

Wrap the query template. {?{searchboxquery}}

1. Edit the page
2. Edit the Search Results web part
3. Click “Change query”

4. In the Query text box, wrap the filters {?{searchboxquery}}

5. When you click Test query, the preview should say “This query returned no results.”
6. Click OK to save the query
7. Click OK to save and close the web part properties
8. Save the page

Custom XSL Web Part Error – Access Denied

Scenario:

I created a custom XSL style sheet for a library web part that would intermittently throw an error for everyone except the admin account (me).

Every morning users were complaining about an error on the web part. I would sign in and try to replicate, but it always worked for me. Then when I’d ask the user to refresh their page and miraculously the error would go away.

Error

ULS logs contained the following information:

SPSecurityContext: Could not retrieve a valid windows identity for username ‘domain\user’ with UPN ‘user@domain.local’. UPN is required when Kerberos constrained delegation is used. Exception: System.ComponentModel.Win32Exception (0x80004005): Access is denied Server stack trace:
 at System.ServiceModel.Channels.AppContainerInfo.GetCurrentProcessToken()
 at System.ServiceModel.Channels.AppContainerInfo.RunningInAppContainer()
 at System.ServiceModel.Channels.AppContainerInfo.get_IsRunningInAppContainer()
 at System.ServiceModel.Channels.PipeSharedMemory.BuildPipeName(String pipeGuid)
 at System.ServiceModel.Channels.PipeSharedMemory.get_PipeName()
 at System.ServiceModel.Channels.PipeConnectionInitiator.GetPipeName(Uri uri, IPipeTransportFactorySettings transportFactorySettings)
 at System.ServiceModel.Channels.NamedPipeConnectionPoolRegistry.NamedPipeConnectionPool.GetPoolKey(EndpointAddress address, Uri via)
 at System.ServiceModel.Channels.CommunicationPool`2.TakeConnection(EndpointAddress address, Uri via, TimeSpan timeout, TKey& key)
 at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
 at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
 at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
 at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
 at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
 at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
 at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown
 at [0]:
 at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
 at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
 at Microsoft.IdentityModel.WindowsTokenService.S4UClient.IS4UService_dup.UpnLogon(String upn, Int32 pid)
 at Microsoft.IdentityModel.WindowsTokenService.S4UClient.CallService(Func`2 contractOperation)
 at Microsoft.SharePoint.SPSecurityContext.GetWindowsIdentity().
No windows identity for “domain\user”.

Root cause:

The SharePoint site’s application pool was configured to recycle every morning at 3:00 AM. This would clear cached authentication, and due to permissions, the XSL style sheet could not be accessed until the administrator logged in.

In addition, according to Hemendra’s response in this post, this can also be caused by an anonymous cache bug.

Solution:

Option 1: Remove auto-recycle settings on the application pool. (The error will re-appear if the site is manually recycled or the server reboots.)

Option 2 (recommended): Create two separate XSL files. The first file will be attached to the web part and, using the xsl:import element, will reference a second XSL file that contains your view styles.

XSL File #1 – Reference.xsl (linked in the Web Part Properties):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="/SiteAssets/Style.xsl"/>

<xsl:template match="/">
<xsl:apply-imports/>
</xsl:template>

</xsl:stylesheet>

xsllink

XSL File #2 – Style.xsl (contains view styles):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<td><xsl:value-of select="catalog/cd/title"/></td>
<td><xsl:value-of select="catalog/cd/artist"/></td>
</tr>
</table>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

NOTE: Save your XSL files in a library where Everyone has at least Read permissions.

Chart Web Part – SharePoint 2013

In SharePoint 2010, there was a Chart Web Part that you could connect to another web part on the same page, to a list anywhere in the site collection, to an external content type, or to data from an Excel workbook.

In SharePoint 2013, this does not exist OOB.

However, if you copy and paste this code and save it as an XML file, you can upload it and use it in 2013!


<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Microsoft.Office.Server.WebControls.ChartWebPart,microsoft.office.server.chart,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" />
<importErrorMessage>Cannot import Chart Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Chart Web Part</property>
<property name="Description" type="string">Helps you to visualize your data on SharePoint sites and portals.</property>
</properties>
</data>
</webPart>
</webParts>

Navigate to the page you where you want to add a chart and go into edit mode.

Click the insert tab and select Web Part.

Click “Upload a Web Part” and browse to the XML file you saved from the code above.

Click Upload.

chart

The page will refresh so you’ll have to go back into the Web Part menu to select the Chart Web Part from the Imported Web Parts category.

chartwebpart.PNG

Click Add and voila!

chartwebpart1.PNG

Save the page before you click on the Data & Appearance or Advance Properties links.

Link To New Item Form

Give users the ability to add items to a list without showing the entire list web part. In my example, I’ve added a “Submit Request” button to a Document Set Welcome Page. Clicking this will open the New Item form for my Tickets list.

docset


<script type="text/javascript">

 function displayLayover(url) {

 var options = SP.UI.$create_DialogOptions();

 options.url = url;

 options.dialogReturnValueCallback = Function.createDelegate(

 null, null);

 SP.UI.ModalDialog.showModalDialog(options);

 }

 </script>

<input type="button" onclick='javascript:displayLayover("/sites/sandbox/mustard/Lists/Tickets/NewForm.aspx")' value="Submit Request">

Steps:

1. Add a Script Editor web part to your page.

2. Click EDIT SNIPPET.

3. Replace the URL in this line with the path to your list’s New Item form (you can also change what the button says by changing the ‘value’):

<input type="button" onclick='javascript:displayLayover("/sites/sandbox/mustard/Lists/Tickets/NewForm.aspx")' value="Submit Request">

NOTE: If your URL looks something like this: /sites/sandbox/mustard/_layouts/15/start.aspx#/Lists/Tickets/NewForm.aspx, remove /_layouts/15/start.aspx# from the path.

embed

4. Click Insert and save the page.

5. To test, click the new “Submit Request” button.

formpopup1

6. Add some information and click Save.

7. Navigate to the list to confirm.

ticket

Edit Form Popup – Drag And Drop

By default, the edit form does not pop up when you drag and drop documents into a library. This piece of JavaScript will force an edit form to pop up for as many documents you drag and drop. For example, if you drag 5 documents at the same time, 5 individual edit forms will pop up in succession.

1. Make sure that the Metadata Navigation and Filtering site feature is enabled.

2. Navigate to and edit the page you are adding this to.

3. Insert a Script Editor web part and embed the following code (no changes need to be made, just copy/paste):


<script unselectable="on">

(function (_window) {

    var maxTimeForReplaceUploadProgressFunc = 10000;

    function replaceUploadProgressFunc() {

        if (typeof _window.UploadProgressFunc != 'undefined') {

            _window.Base_UploadProgressFunc = _window.UploadProgressFunc;

            _window.UploadProgressFunc = Custom_UploadProgressFunc;

            console.log('replaced dialog');

        } else if (maxTimeForReplaceUploadProgressFunc > 0) {

            maxTimeForReplaceUploadProgressFunc -= 100;

            setTimeout(replaceUploadProgressFunc, 100);

        }

    }

    setTimeout(replaceUploadProgressFunc, 100);


    function Custom_UploadProgressFunc(percentDone, timeElapsed, state) {

        _window.Base_UploadProgressFunc(percentDone, timeElapsed, state);

        var messageType = ProgressMessage.EMPTY;

        switch (state.status) {

            case 1:

                messageType = ProgressMessage.VALIDATION;

                break;

            case 3:

                messageType = ProgressMessage.UPLOADING;

                break;

            case 4:

                messageType = ProgressMessage.UPLOADED;

                OpenEditFormForLastItem(state);

                break;

            case 5:

                messageType = ProgressMessage.CANCELLED;

                break;

        }



        function OpenEditFormForLastItem(state) {

            var caml = '';

            caml += "<View>";

            caml += "<Query>";

            caml += "<Where>";



            if (state.files.length > 1) {

                caml += "<In>";

                caml += "<FieldRef Name='FileLeafRef'/>";

                caml += "<Values>";

            } else {

                caml += "<Eq>";

                caml += "<FieldRef Name='FileLeafRef'/>";

            }



            state.files.forEach(function (file) {

                //only succesfull uploaded files that arent overwrites

                console.log(file);

                if (file.status === 5 /*&& !file.overwrite*/) {

                    caml += "<Value Type='File'>" + file.fileName + "</Value>";

                }

            }, this);


            if (state.files.length > 1) {

                caml += "</Values>";

                caml += "</In>";

            } else {

                caml += "</Eq>";

            }


            caml += "</Where>";

            caml += "<OrderBy><FieldRef Name='ID' Ascending='True' /></OrderBy>";

            caml += "</Query>";

            caml += "<ViewFields><FieldRef Name='ID' /></ViewFields>";

            caml += "<RowLimit>500</RowLimit>";

            caml += "</View>";

            console.log(caml);



            var cntxt = SP.ClientContext.get_current();

            var web = cntxt.get_web();

            var list = web.get_lists().getByTitle(window.ctx.ListTitle);

            var query = new SP.CamlQuery();

            query.set_viewXml(caml);

            var items = list.getItems(query);

            cntxt.load(list, 'DefaultEditFormUrl');

            cntxt.load(items);

            cntxt.executeQueryAsync(function () {

                var listEnumerator = items.getEnumerator();

                function openEditForItem() {

                    if (listEnumerator.moveNext()) {

                        var item = listEnumerator.get_current();

                        var id = item.get_id();



                        var options = SP.UI.$create_DialogOptions();

                        options.title = "Add File Metadata";

                        options.url = list.get_defaultEditFormUrl() + '?ID=' + id;

                        options.autoSize = true;

                        options.dialogReturnValueCallback = openEditForItem;

                        SP.UI.ModalDialog.showModalDialog(options);

                    } else {

                        location.reload();

                    }

                }

                openEditForItem();

            }, function (error, args) {

                    console.log("failed to get new uploaded items");

                    console.log(error);

                    console.log(args);

                });

        }

    }

})(window);

</script>

4. Click OK and save the page.

5. Confirm that the edit form pops up when you drag and drop documents.

Drop-Down Menu Of Links

To add a drop-down menu populated by links to other parts of your site, add a Script Editor Web Part and embed the following code:


<!DOCTYPE html>
<html>
<body>

<select name="Page">
<option value="">Jump to...</option>
<option value="About">About</option>
<option value="ContactUs">Contact Us</option>
<option value="EmployeeResources">Employee Resources</option>
</select>

<input type="button" value="Go" onclick="window.open(location.href='http://sp2013/sites/company/SitePages/' + Page.value)"/>

</body>
</html>

Make sure you replace the URL with your site’s URL, and change the option values to the names of your pages. The text between the option tag is the title of the page or what you want the drop-down menu to show.

DropDown

Custom Quick Edit Button

To add a custom Quick Edit button to a page or view, add a Script Editor Web Part and embed the following code. Make sure you change the number in [WPQ2SchemaData] to the ID of the Web Part you want to Quick Edit. You can find that by inspecting the list or library Web Part using Developer Tools (F12).

 


<!DOCTYPE html>
<html>
<body>
<button onclick="QuickEditFunction();return false;">Quick Edit</button>

<script>
function QuickEditFunction()
{
InitGridFromView(window['WPQ2SchemaData'].View);
}
</script>

</body>
</html>