Showing posts with label SharePoint Customization. Show all posts
Showing posts with label SharePoint Customization. Show all posts

2/21/2016

Hide the Attachments Link in a SharePoint Form

 

The problem… While we do want site visitors to see the list items, we don’t want them to see or click the list’s attachments.

More SharePoint Customization tricks!
More Site Owner articles.
More articles about the SPSecurityTrimmedControl
image

One approach is to use CSS and a handy SharePoint control. You could also write a JavaScript solution. Here we will look at the CSS option.

Note: This is not security! This is hiding some HTML using CSS. Users can right-click and select View Source to discover the text hidden by the CSS.

 

General pattern:

  1. View the DispForm.aspx page (the view properties popup in SP 2010) for an item in the list.
  2. Press F12 to open the IE Developer Tools.
  3. Use the Internet Explorer F12 panel’s Select Element button to discover an appropriate tag and ID that could changed by CSS to show/hide the content.  (For this example it happens to be “idAttachmentsRow”.)
    image
  4. Edit the DispForm.aspx page using SharePoint Designer.
  5. Add CSS to hide the tag from everyone.
  6. Add a SharePoint control with additional CSS to unhide the content for users with at least the Edit permission. Set the SharePoint control to only display its content for people who can edit list items.

The SPSecurityTrimmedControl

The magic here is that the SPSecurityTrimmedControl can selectively display content based on a user’s assigned permission. As an example, users with the Read permission level do not have the EditListItems permission while members and owners do. Note that the control can only be set to a single permission, not a Permission Level or group.

More detailed steps:

  1. Open SharePoint Designer and your site.
  2. Click Lists and Libraries and your list.
  3. Click the DispForm.aspx file.
  4. In the ribbon click Advanced Mode.
  5. Find the PlaceholderMain Content tag (<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">)
  6. Add the following block of HTML just after that tag.
  7. Save your changes and test.

 

SharePoint 2010 (and probably 2007) version:

<style type="text/css">
  #idAttachmentsRow { display:none }
</style>
<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="EditListItems">
  <style type="text/css">
    #idAttachmentsRow { display:inline }
  </style>
</Sharepoint:SPSecurityTrimmedControl>

SharePoint 2013 and SharePoint Online / O365 (and probably 2016) version:

<style type="text/css">
  #idAttachmentsRow { display:none !important }
</style>
<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="EditListItems">
  <style type="text/css">
    #idAttachmentsRow { display:table-row !important}
  </style>
</Sharepoint:SPSecurityTrimmedControl>

A list of the PermissionsStrings can be found here: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbasepermissions.aspx

More about using SPSecurityTrimmedControl can be found here: http://techtrainingnotes.blogspot.com/2009/07/sharepoint-run-javascript-based-on-user.html

 

.

11/23/2015

SharePoint 2013: Hide JSLink from Team Members

This article applies to SharePoint Online, SharePoint 2013 and 2016.

 

Let's start with a couple "did you knows"…

Did you know:

  • All users with Edit and Contribute permission levels can edit the home page of your site?
  • The same users can edit or delete any page in the Site Pages library.?
  • They can also edit the web parts on that page? And use advanced options like JS Link?

As part of your SharePoint governance or best practices you may want to limit who can use some of the more advanced customization features of SharePoint 2013 and 2016. JS Link, is after all, JavaScript programming and it can cause issues for daily support and the upgrade to future versions of SharePoint.

Before we get into locking down just JS Link, let's address the "did you knows". You may want to think about changing the permissions of Site Pages, Site Assets and a few other libraries to read only for all users except for Site Owners. Those libraries really should not be open for all to edit.

 

About JS Link

JS Link is a really cool technology introduced with SharePoint 2013 to let us customize web parts, views and list forms without "un-ghosting" pages using SharePoint Designer. It lets us create a JavaScript text file, store it in a library, and then link it to a web part or a form. If you are a developer, you can also use JS Link with Site Columns and Site Content Types. One of the benefits of JS Link is that the customization file can be created once, stored in a library and then be linked into many web parts and forms. When you need a change in the future, you only need to edit a single JavaScript file and not dozens or hundreds of web parts.

For web parts, JS Link is added in the Miscellaneous section of the web part properties panel.

image

 

Hiding JS Link

As SharePoint does not have a "switch" where we can just turn off the use of JS Link, we will need to come up with a CSS or JavaScript solution. If you add the following CSS to your master page (lots of ways to do this) then the JS Link box will be hidden.

<style type="text/css">
  input[id$="_JSLink_EDITOR"] {
    display:none;
  }
  label[for$="_JSLink_EDITOR"] {
    display:none;
  }
</style>

 

While we are at it, you may also want to hide the XSL Link option too:

<style type="text/css">
  input[id$="_JSLink_EDITOR"] {
    display:none;
  }
  label[for$="_JSLink_EDITOR"] {
    display:none;
  }
  input[id$="_XslLink_EDITOR"] {
    display:none;
  }
  label[for$="_XslLink_EDITOR"] {
    display:none;
  }
</style>

 

But what about the Site Owner?

If you want some users to still be able to edit the JS Link and XSL Link options then we can give those back using a SharePoint Security Trimmed Control. You just need to pick a permission that is unique that that group of users such as Add and Customize Pages. In the example below we take away JS Link from all users, and then give it back to select users.

<style type="text/css">
  input[id$="_JSLink_EDITOR"] {
    display:none;
  }
  label[for$="_JSLink_EDITOR"] {
    display:none;
  }
  input[id$="_XslLink_EDITOR"] {
    display:none;
  }
  label[for$="_XslLink_EDITOR"] {
    display:none;
  }
</style>
<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="AddAndCustomizePages"> <!-- Let owners and designers see the JSLink options --> <style type="text/css"> input[id$="_JSLink_EDITOR"] { display:inline; } label[for$="_JSLink_EDITOR"] { display:inline; } input[id$="_XslLink_EDITOR"] { display:inline; } label[for$="_XslLink_EDITOR"] { display:inline; } </style> </SharePoint:SPSecurityTrimmedControl>

 

.

11/16/2015

Add a Crumb Trail to SharePoint 2013

 

Solution #1: Restore the SharePoint 2010 Navigate Up button

See here: http://techtrainingnotes.blogspot.com/2014/06/sharepoint-2013-restoring-2010-navigate.html

[image%255B21%255D.png]

 

Solution 2: Add an always displayed site crumb trail

If you only need a crumb trail to be able to navigate back up to a parent site then we can add a site map control to the master page like this:

<span style="font-size:8pt;">
  <asp:SiteMapPath id="ContentMap2" 
       SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" 
       runat="server"/> 
</span>

Edit your master page, search for "</h1>" and add the HTML above just below the "</h1>".

The result will look like this:

image

 

Solution 3: Add an always displayed site and folder crumb trail

See the link below for a nice solution that reuses the SharePoint:ListSiteMapPath control from the SharePoint 2010 Navigate Up control and reformats it into a single line.

http://www.broculos.net/2013/12/sharepoint-2013-branding-show-folder.html

The result looks like this:

image

Notes:

  • The author of that article was working with a Publishing feature Design Manager master page and wrapped the control inside of an HTML comment block. (<!--   -->) You will not need this for a non-publishing site master paged edited in SharePoint Designer.
  • The article's sample CSS code needs to be placed inside of a linked CSS file or inside of style tags. <style type="text/css">  ,,,  </style>
  • To get the crumb trail display exactly where I wanted it I added it just after the "</h1>" tag in the master page and added this to the article's CSS:
      .my-breadcrumb {
         margin-top:0px;
         margin-left:3px;
         font-size:8pt;
      }

 

Other options

Here's a project that adds a folder crumb trail to library web parts using JS Link: SharePoint 2013: Folder Navigation/Breadcrumb
http://social.technet.microsoft.com/wiki/contents/articles/19713.sharepoint-2013-folder-navigationbreadcrumb.aspx and here: http://ranaictiu-technicalblog.blogspot.com/2013/07/sharepoint-2013-folder-navigation-for.html

The only disadvantage to this solution is that you need to make a change to every list/library/view web part.

 

.

11/08/2015

Fifty+ SharePoint 2013 Sample Background Images

The following applies to SharePoint 2013 and SharePoint Online / Office 365.

Theme Background Images

When designing a theme for your site you can use a background image for the page. Did you know that SharePoint 2013 includes more than fifty 1024 x 768 sample images? Ten of the sample themes use the first ten of these images. These ten images and forty more can be found at the following URLs:

https://yourServerDomain/_layouts/15/images/image_bg002.jpg
or
https://yourServerDomain/sites/yourSite/_layouts/15/images/image_bg002.jpg

Replace the “image_bg002.jpg” with the names from the samples below.

 

Background images used with the sample themes:

image

 

Additional Background Images Available:

image
image

image

image

image

 

And a few more interesting images from that folder:

image

.

10/27/2015

SharePoint: Sort and Filter on One Column While Displaying Another

This article includes both 2010 and 2013 examples.

Let's say you wanted to display a Date/Time down to the minute or second, but you wanted the column heading to filter by days or months. By default the column filter dropdown displays one each of what ever it finds in the column, or in the case of dates, the nearest day.

image

But if you want just the months or years in the dropdown, then maybe something like this:

image        image

 

It's not to hard to do in SharePoint 2010, and fairly easy in SharePoint 2013

In SharePoint 2010 we still have a fully working SharePoint Designer that can easily edit web parts. In SharePoint 2013, Designer is pretty much broken for web part work, which is just as well as we should be looking at the newest tools in 2013 for our customizations. In this example we will be using JS Link for 2013.

 

Steps for SharePoint 2010

The basic steps:

  • Create a new list named "Event Announcements".
  • Add a Date and Time column named "EventDate".
  • Add a Calculated column named "Event Date" to display a YYYY-MM version of the date that can be used to filter by month.
  • Use SharePoint Designer to display the full date in the calculated column by hand customizing the XSLT.

Note: Although the names of my columns differ only by a space, you can use any column names you like. I will use EventDate for data entry and Event Date for display.

Steps:

  1. Go to your site and create a test list. For this example an Announcements list would be a good choice.
  2. Create a new column named "EventDate". (You will enter your date data here.) 
    1. In the List ribbon click Create Column.
    2. Enter "EventDate" as the name.
    3. Set the type to Date and Time.
    4. Set Date and Time Format to Date & Time.
    5. Click OK.
  3. Create a new column named "Event Date". (This column will control the filter grouping.)
    1. In the List ribbon click Create Column.
    2. Enter "Event Date" as the name.
    3. Set the type to Calculated.
    4. Enter this formula:
         =TEXT([EventDate],"yyyy-mm")
      or for years instead of months:
         =TEXT([EventDate],"yyyy")
    5. Set The data type returned from this formula to Single line of text.
    6. Click OK.
  4. Add some sample data with dates spread across two or three different months.
     
  5. Open SharePoint Designer 2010 and open your site.
  6. Click Lists and Libraries and click your list.
  7. Find and click your view (I used All Items).
  8. If the screen is not in Split view click Split at the bottom of the screen.
  9. In the Code view pane click in the web part code. (The code without the yellow background.)
  10. In the List View Tools / Design ribbon click Customize XSLT and Customize Entire View.
    image
  11. In the design view click on any one of the dates in the EventDate column.
       image
  12. Verify the field name by looking up a few lines for FieldRef_ValueOf. My field is EventDate.
       image
  13. In the design view click on any one of the dates in the Event Date column. (the calculated column)  This will highlight a line in the Code view.
  14. Edit the "value-of" element to change from this:
      <xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
    to this:
      <xsl:value-of select="$thisNode/@*[name()='EventDate']"/>
    Note that you are replacing the expression "current()/@Name" to the name of the field wrapped in single quotes. I.e. 'EventDate'. EventDate is column from which you want to copy the data.
  15. Save the file.
  16. Return to the browser and test the view. You can edit the view and remove the EventDate column as we only need the Event Date column.
       image

 

Steps for SharePoint 2013

The basic steps:

  • Create the test list and columns. (Same steps as for 2010)
  • Create the JS Link JavaScript file.
  • Upload or save the file to a SharePoint library.
  • Edit the view's web part and link to the JS File.

Steps:

  1. Go to your site and create a test list. For this example an Announcements list would be a good choice.
  2. Create a new column named "EventDate". (You will enter your date data here.) 
    1. In the List ribbon click Create Column.
    2. Enter "EventDate" as the name.
    3. Set the type to Date and Time.
    4. Set Date and Time Format to Date & Time.
    5. Click OK.
  3. Create a new column named "Event Date". (This column will control the filter grouping.)
    1. In the List ribbon click Create Column.
    2. Enter "Event Date" as the name.
    3. Set the type to Calculated.
    4. Enter this formula:
         =TEXT([EventDate],"yyyy-mm")
      or for years instead of months:
         =TEXT([EventDate],"yyyy")
    5. Set The data type returned from this formula to Single line of text.
    6. Click OK.
  4. Add some sample data with dates spread across two or three different months.
     
  5. Open SharePoint Designer 2013 and your site.
  6. In the Navigation area click Site Assets. (or any other library)
  7. Right-click in any empty space in the file area and select New and HTML.
  8. Right-click the new file and rename it to GroupByMonthJSLink.js (any name will do)
  9. Click the new file and then click Edit File.
  10. Select all of the HTML and delete it.
  11. Enter the JavaScript listed below.
  12. Save the file.
  13. Go to the new list.
  14. Click Settings (gear) and Edit Page.
  15. In the list’s web part click the dropdown and click Edit Web Part.
  16. In the web part properties panel expand Miscellaneous.
  17. Enter the following path into the JS Link box:
    ~site/SiteAssets/GroupByMonthJSLink.js
    Note: "~site" points to current site/subsites URL while "~sitecollection" points to the top level site's URL.
  18. Click Apply. (You should see the change to the Event Date column.)
  19. Click OK
  20. In the Page ribbon click Stop Editing.
  21. Test! You can edit the view and remove the EventDate column as we only need the Event Date column.
       image

 

The JavaScript File

(function () { 

  // do all of the setup work...
  var TTNctx = {};
  TTNctx.Templates = {}; 

  // configure the Event_x0020_Date field to copy the EventDate values 
  // into the Event_x0020_Date column
  TTNctx.Templates.Fields = { 
    "Event_x0020_Date": 
{ "View": function (ctx) {return ctx.CurrentItem.EventDate} } }; // register the override SPClientTemplates.TemplateManager.RegisterTemplateOverrides(TTNctx); })(); // end of function

 

.

10/25/2015

SharePoint: Launch a Site Workflow from a Link or Button

The following has been tested with SharePoint 2010 and 2013…

There are a lot of questions in the various forums on how to start a Site Workflow, mostly because it is a bit hard to find in SharePoint. For those looking for only that, here's the basic steps:

Start a Site Workflow

  1. Click Site Actions (2010) or Settings (gear) (2013).
  2. Click View All Site Content (2010) or Site Contents (2013).
  3. Click Site Workflows.
  4. Click the workflow!
  5. If displayed, complete the workflow initiation form. (2010 workflows always display an Initiation Form, even if has only OK and Cancel buttons.)

 

Launching a workflow from a link, button or Quick Launch

Instead of telling your users to go find the Site Workflows page it might be better just to give them a link or button to click. All we need is to know how (and where) to copy and paste the URL or JavaScript and then how to use that to create the link.

image

In SharePoint 2010 there are only two ways to launch a Site Workflow from a link, while in SharePoint 2013 there are four!

For 2010:

SharePoint 2010 Site Workflows have two possible URLs to launch workflows, one for workflows with InfoPath forms and one for workflows with ASPX forms. The kind of form you get depends on your edition of SharePoint. For Foundation, SharePoint Designer creates ASPX forms, while for Standard and Enterprise SharePoint Designer creates InfoPath (.XSN) forms. You can force ASPX forms by disabling the hidden "OffWFCommon" feature. (See note at the end of this article.) 

For Foundation: (ASPX forms)

http://yourServer/sites/yourSite/Workflows/yourWorkflowName/yourWorkflowname.aspx?TemplateID={030c0f5b-f4be-4c32-9fe6-d1fbf18080e1}&Source=http%3A%2F%2FyourServer%2Fsites%2FyourSite%2F%5Flayouts%2Fworkflow%2Easpx

For Standard and Enterprise: (InfoPath forms)

http://yourServer/sites/yourSite/_layouts/IniWrkflIP.aspx?TemplateID={6bc58ac2-b39c-4e35-a644-43335e966291}&Source=http%3A%2F%2FyourServer%2Fsites%2FI%2F%5Flayouts%2Fworkflow%2Easpx

The GUID in the URL is the unique ID for your workflow.

 

For 2013:

SharePoint 2013 supports two kinds of workflows, 2010 and 2013. As a result we end up with three ways to launch a workflow. The first two are similar to the 2010 URLs listed above. Only SharePoint 2010 style workflows are available in Foundation. 2013 style workflows are only available in Standard and Enterprise if your server administrators have installed support for them.

For Foundation 2013 and SP 2010 style workflows: (ASPX forms)

I'm assuming (a dangerous thing to do!) that the URL is similar to 2010's. In any case we will just be copying the URL.

For Standard and Enterprise 2013 and SP 2010 style workflows: (InfoPath forms) 

https://yourServer/sites/yourSite/_layouts/15/IniWrkflIP.aspx?TemplateID={b5760949-b13a-4348-a309-65a01f8fbde7}&Source=https%3A%2F%2FyourServer%2Fsites%2FyourSite%2F%5Flayouts%2F15%2Fworkflow%2Easpx

For SharePoint 2013 workflows without initiation forms started from a JavaScript function call:

javascript:StartWorkflow4('7032d6a6-66e0-4c22-9483-2971b90b0e64', '', '')

For SharePoint 2013 workflows with or without initiation forms started from a URL:

https://yourServer/sites/yourSite/wfsvc/20a711570d0549ff83adafde04bce160/WFInitForm.aspx?TemplateID={7032d6a6-66e0-4c22-9483-2971b90b0e64}&WF4=1&Source=https%3A%2F%2FyourServer%2Fsites%2FyourSite

 

Steps to Create Links for Workflows in General

No matter with version or edition, if you are working with hyperlinks to start workflows your links will be created by copying the URL to the workflow and using it to launch the workflow from Quick Launch, an anchor tag (<A>), an INPUT tag or a BUTTON tag.

Copying the URL or JavaScript:

  1. For SharePoint 2010: Click Site Actions, View All Site Content. (or click All Site Content in the Quick Launch area)
    For SharePoint 2013: Click Settings (gear) and Site Contents. (or click Site Contents in the Quick Launch area)
  2. Click Site Workflows. (top right corner of page)
  3. Right-click the workflow and click Copy Shortcut. (or right-click the workflow, click Properties and copy the URL from there.
  4. If the copied link is a URL and not JavaScript:  (JavaScript will only be found for SharePoint 2013 style workflows that do not have an Initiation Form.)
    1. Paste the URL in to Notepad or other text editor.
    2. Remove the absolute part of the path (the http://servername). This is not required, but is a best practice.
      https://yourServerName/sites/yourSite/_layouts/15/IniWrkflIP.aspx?TemplateID={b5760949-b13a-4348-a309-65a01f8fbde7}&Source=https%3A%2F%2FyourServerName%2Fsites%2Ftraining%2F%5Flayouts%2F15%2Fworkflow%2Easpx
    3. Edit the URL after &Source to the URL where you want the user to land after starting the workflow. (Usually the same page they started from, but could be an "after the workflow instructions" page.)
      /sites/yourSite/_layouts/15/IniWrkflIP.aspx?TemplateID={b5760949-b13a-4348-a309-65a01f8fbde7}&Source=%2Fsites%2Ftraining%2FSitePages%2FFurthreInstructions%2Easpx
      Notes: %2F  = "/" and %2E = "."
    4. Copy the edited URL.

 

Adding a link via Quick Launch

I won't add all of the details here, but basically:

  • For 2010 team sites: Site Actions, Site Settings, Quick Launch
  • For 2010 publishing sites: Site Actions, Site Settings, Navigation, Current Navigation
  • For 2013 team sites: Settings (gear), Site Settings, Quick Launch
    or click EDIT LINKS in the Quick Launch area, click +link 
  • For 2013 publishing sites: Settings (gear), Site Settings, Navigation, Current Navigation

 

Adding Links via HTML

You can add custom HTML to Wiki pages, ASPX pages, Links lists and Content Editor Web Parts.

<input type="Button" onclick="window.location='yourCopiedUrlGoesHere'" value="click me">

<button type="Button" onclick="window.location='yourCopiedUrlGoesHere'" >click me</button>

<a href="yourCopiedUrlGoesHere">click me</a>

 

Adding Links via JavaScript

This option only applies to SharePoint 2013 and only for 2013 style workflows without Initiation Forms. (i.e. no user interaction before the workflow starts.) If you right-click a workflow link in Settings, Site Contents, Site Workflows (workflow.aspx), click Properties and see JavaScript instead of a URL it will probably look like this:
  javascript:StartWorkflow4('7032d6a6-66e0-4c22-9483-2971b90b0e64', '', '')

The nice thing about launching a workflow from StartWorkflow4 is that it is done using a CSOM web service call and does not cause the user to move to another page. Just click, and the workflow starts. The problem for us is that the StartWorkflow4 function is not available from every page in SharePoint. It's only available from workflow.aspx. To duplicate the code from that page you will need to add a link to a SharePoint JavaScript library and copy some JavaScript code from the workflow.aspx page.

The following assumes you are editing an ASPX page in SharePoint Designer, or you have placed the code in a text file and linked to that text file from a Content Editor Web Part.

Steps:

  1. Open SharePoint Designer 2013 and the open your site.
  2. If you are directly editing a page, open that page for editing. (You may need to click Advanced Mode in the ribbon.)
  3. If you are using a Content Editor Web Part for the code:
    1. Click Site Assets (could also use Site Pages or any other library).
    2. Right-click in the white space in the file list area and click HTML.
    3. Select all of the HTML and delete it.
  4. Add a link to the workflowservices.js library:
      <script type="text/javascript" src="/_layouts/15/sp.workflowservices.js"></script>
  5. Add a control to fire the JavaScript that you copied from the workflow page:

    <input type="Button" onclick="javascript:StartWorkflow4('7032d6a6-66e0-4c22-9483-2971b90b0e64', '', '')" value="click me">

    <button type="Button" onclick="javascript:StartWorkflow4('7032d6a6-66e0-4c22-9483-2971b90b0e64', '', '')">click me</button>

    <a href="" onclick="javascript:StartWorkflow4('7032d6a6-66e0-4c22-9483-2971b90b0e64', '', '') ; return false;">click me</a>
  6. Visit the Site Workflow page: Settings (gear), Site Contents, Site Workflows.
  7. Either use the browser's View Source command or press F12 and use the DOM explorer to view the HTML of the page.
  8. Search for StartWorkflow4.
  9. Browse backwards from there and find the previous <script… tag and copy from that <script tag to the matching </script> tag.
  10. Paste this into your SharePoint Designer file.
  11. Save the file.
  12. If you are directly editing a page, go to a browser and test the link.
  13. If you are using a Content Editor Web Part for the code:
    1. Go to the browser, navigate to the page where you would like to have the link.
    2. Edit the page.
    3. Insert a Content Editor Web Part.
    4. Edit the web part and in the properties panel enter the URL to your code page. Something like:
      https://yourServer/Sites/yourSite/SiteAssets/WorkFlowLinkCode.html
    5. Click OK in the properties panel.
    6. Save the page and test the link.

 

Enjoy!

 

 

Note: The OffWFCommon Feature

I have only done limited testing here… so buyer beware, and only do this on a test or dev farm.

I wanted to create a SharePoint Designer workflow that used ASPX forms instead of InfoPath forms as they were easier to customized for this project. I simply deactivated the OffWFCommon feature (by GUID), closed and reopened SharePoint Designer and then created a new workflow, which magically had ASPX forms. Not knowing what the side effects were, I reactivated the feature as soon as the workflow was written. This is a Site Collection level feature. As it is a hidden feature, you will need to use STSADM, PowerShell or code to activate or deactivate it.

Note: Even if it is on the server, activating this feature won't give you usable InfoPath forms on SharePoint Foundation!

Using STSADM:
   stsadm -o deactivatefeature -id C9C9515D-E4E2-4001-9050-74F980F93160 -url <url>

Using PowerShell:
   Disable-SPFeature -Identity c9c9515d-e4e2-4001-9050-74f980f93160 -url <url>

If you are curious, the feature lives here: (14 for 2010, 15 for 2013)
  C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\OffWFCommon

 

.

10/14/2015

SharePoint PreCancelAction

 

SharePoint does not have a PreCancelAction. I created what I needed for one project, and present it here for your creative uses and enhancements. No warranties and no support… but the price is right!

 

PreSaveAction

When you click Save from an ASPX list form SharePoint checks to see if you have added a PreSaveAction JavaScript function to the page. If you have included the function, it is called, your code run and then your code can return a True or False to allow the save to continue, or to cancel it. You can add this function directly to the page, via a Content Editor Web Part, and in 2013 as a JS Link. Do a web search to find examples of its use.

PreSaveAction sample:

<script type="text/javascript">
 function PreSaveAction() {
  // do pre-save work here: validation, messages, etc.
  alert('Thank you for your suggestion!');
  return true;  // return true to continue with the save 
                // or return false to cancel the save
 } 
</script>

 

PreCancelAction

I needed a popup message to stress "Changes not saved", so I put together some JavaScript that intercepts the cancel and displays a message to the user. 

All of the examples below look for INPUT tags with a VALUE of "Cancel". You may want to change this line to match your language requirements. The code also only intercepts INPUT tags that include "STSNavigate" in their onclick code. This is to avoid intercepting the attachment dialog's cancel button. The code stores all of the original onclick code in a globally scoped array named TTNoriginalFunctions as each Cancel button on the form may have had unique code.

 

Warn the user on cancel:

This example does not call your functions, it just intercepts the Cancel buttons and runs the imbedded alert code.

var TTNoriginalFunctions = [];
var TTNCounts = 0;
var TTNinputs  = document.getElementsByTagName("input")
for (var i = 0; i<TTNinputs.length; i++)
{
  if (TTNinputs[i].value == "Cancel") 
  {
    if (TTNinputs[i].onclick)
    { 
      if (String(TTNinputs[i].onclick).indexOf("STSNavigate")>-1)
      {
        TTNoriginalFunctions[TTNCounts] = TTNinputs[i].onclick;
        TTNinputs[i].onclick = new Function(" return function () { alert('Changes not saved'); TTNoriginalFunctions[" + TTNCounts + "]();}")();
        TTNCounts++;
      } 
    }
  }
}

 

Callable as a function:

This is the same as the above, but wrapped up in a function that you can call it from your code. You pass in the custom code to run as a string. This uses "new Function" to build the code from a string.

var TTNoriginalFunctions = [];

function TTNPreCancelAction(yourFunctionAsString)
{
  var TTNCount = 0;
  var TTNinputs  = document.getElementsByTagName("input")
  for (var i = 0; i<TTNinputs.length; i++)
  {
    if (TTNinputs[i].value == "Cancel") 
    {
      if (TTNinputs[i].onclick)
      { 
        if (String(TTNinputs[i].onclick).indexOf("STSNavigate")>-1)
        {
          TTNoriginalFunctions[TTNCount] = TTNinputs[i].onclick;
          TTNinputs[i].onclick = new Function(" return function () { " + yourFunctionAsString + "; TTNoriginalFunctions[" + TTNCount + "]();}")();
          TTNCount++;
        } 
      }
    }
  }
}


TTNPreCancelAction("alert('changes not saved')");

 

A solution that works more like SharePoint's PreSaveAction:

You could add the TTNPreCancelAction function listed below to your master page or an existing linked JavaScript library. You can then add a PreCancelAction function to forms as needed using SharePoint Designer edits, Content Editor Web Parts or JS Link, just like the PreSaveAction functions. Your PreCancelAction function must return "true" or "false".

// Add this function to a form
function PreCancelAction()
{
  alert('Changes not saved!'); return true;
  //return confirm('Are your sure? Data will be lost!')
}


// Add this code to each form, or once in the master page.
var TTNoriginalFunctions = [];
var TTNCount = 0;
function TTNPreCancelAction()
{
    var TTNinputs  = document.getElementsByTagName("input")
    for (var i = 0; i<TTNinputs.length; i++)
    {
      if (TTNinputs[i].value == "Cancel") 
      {
        if (TTNinputs[i].onclick)
        { 
          if (String(TTNinputs[i].onclick).indexOf("STSNavigate")>-1)  // ignore the Attachments Cancel!
          {
            TTNoriginalFunctions[TTNCount] = TTNinputs[i].onclick;
            TTNinputs[i].onclick = new Function(" return function () { if ('function'==typeof(PreCancelAction)) {if (!PreCancelAction()) {return false} }; TTNoriginalFunctions[" + TTNCount + "]();}")();
            TTNCount++;
          } 
        }
      }
    }
}

TTNPreCancelAction()  //intercept the Cancel buttons
 

 

 

Have a better solution? Post a comment below!  Smile

.

8/07/2015

Hiding the Evil SharePoint 2013 Share Buttons!

 

SharePoint introduced Share buttons to make it easy for users to quickly share a site, folder or document. This introduced several administration, security and governance problems for administrators. Mostly because the act of sharing a document breaks inheritance on the file. Whether this is "evil" or not depends on the way you need to use SharePoint. 

Here's a sample flow:

  • We have a library for 100 sales documents. Currently the Sales Managers group and five other users have access to the library and its contents.
  • Someone clicks the Share button on a document.
    • If the user is not an owner and does not have the Manage Lists permission, then a request is added to the Site Owners. Site Owners, if they ever discover the request, can approve or reject it.
  • Inheritance is broken on the document. Existing permissions are copied to the file. The user is added to the document's permissions list.
  • Now the fun begins…
    • A new user or group is given permissions to the library.
    • They only see 99 documents! (The missing document has unique permissions and no longer inherits permissions from the library.)

After inheritance is broken you have to remember to manage the permissions of each individual broken inheritance document. Now think about 50 libraries, each with where the Share button has been clicked on a 1000 documents. Job security at the minimum!

 

Just how many Share buttons are there?  
(Let me count the ways…)

The Share the site button:

   image

The Share a document button in the "QCB" (Quick Control Block?) bar:

   image

The Share a document button in the FILES ribbon :

   image

The Share a document button in the "…" pop out:

   image

The Share a document link in the "… …" menu:

   image

The INVITE PEOPLE button in create a new folder:

   image

The Invite People button in the Shared With dialog box:

   image

Did I miss any?

(I started on this article a few times, but each time I found yet another Share button!)

 

Disabling using Views

You can hide the Share button that's just above the library by switching to any other view style than"Default". This also hides all of the other links in the "QCB" (Quick Control Block?) bar.

image

The Share button will be grayed out in the FILE ribbon if you select a Style other than Default and Shaded, or disable "Tabular View - Allow individual item checkboxes".

Disadvantages? These styles do not display a checkbox, even if "Tabular View - Allow individual item checkboxes" is checked. Without the checkbox most of the options in the FILE ribbon are disabled.And… this approach only hides one of the Share buttons.

 

Disabling the Share buttons using CSS

The easiest way, at least until Microsoft gives us an option to turn them off, is to add CSS to the Master Page. Some of the buttons has convenient IDs while some can be found using a class. While you could merge all of the selectors into one line, I broke them out so you could choose which Share features you would like to hide or keep.

In my project I uploaded the CSS file to the Site Assets library. You could place the CSS file in any library where your users have at least read access, or in the layouts folder on the server. You would then link to the file something like this:

<link rel="stylesheet" type="text/css" 
href="https://yourServer/sites/yourSite/SiteAssets/nosharebuttons.css"></link>

Or maybe:

<link rel="stylesheet" type="text/css" href="/_layouts/nosharebuttons.css"></link>

 

The CSS:

/* CSS to hide the various Share buttons and links */
/* from TechTrainingNotes.blogspot.com             */
/* Use at your own risk. Batteries not included.   */

/* Hide Site Share button (page top right) */
#ctl00_site_share_button  {
 display:none !important;
}

/* Hide library toolbar (QCB) Share button */
.js-listview-qcbShareButton {
 display:none !important;
}

/* Hide the Share in the ... popout */
.js-callout-actionsMain span:nth-child(2) {
    display:none !important;
}


/* Hide the Share in the ... ... menu */
a[title="Share"] {
 display:none !important;
}


/* Hide the INVITE PEOPLE button in Create Folder */
#csfd_invitePeopleBtn {
 display:none !important;
}

/* Hide the Share button in the FILES ribbon */
#Ribbon\.Documents\.Share\.ShareItem-Large {
 display:none !important;
}

/* Hide the Invite People button in the Shared With dialog */
#lnkShrItem {
 display:none !important;
}

 

Here's the "one line" version:

/* CSS to hide the various Share buttons and links */
/* from TechTrainingNotes.blogspot.com             */
/* Use at your own risk. Batteries not included.   */


#ctl00_site_share_button, 
  .js-listview-qcbShareButton, 
  .js-callout-actionsMain span:nth-child(2), 
  a[title="Share"], 
  #csfd_invitePeopleBtn, 
  #Ribbon\.Documents\.Share\.ShareItem-Large, 
  #lnkShrItem 
{
 display:none !important;
}

 

.

7/09/2015

SharePoint 2013: Hide List and Library Column Headings

 

This is an update to an older article to include support for SharePoint 2013.


Hiding Column Headings

I had a request to hide the column headings of a list displayed in a web part. First thought was that they wanted to hide the toolbar, but they were asking about the clickable column headings. I think they were wanting to make a page look more like a regular web page instead a page full of lists. By the way, this makes for a better way to display a view with only one column.

Note: This will of course remove the ability of the site visitor to sort and filter the web part.

Note: This will also work in the view page (view pages use web parts!), but in SharePoint 2010 and 2013 adding a web part to a view page will change how the ribbon gets displayed and will remove the View dropdown menu from the title area crumb trail.

Before:

image

After:

image

With Toolbar set to "No Toolbar":

image

Remove additional clutter…

You can edit the web part and then click "Edit the current view" further clean up the display of the list.

  • Remove the checkbox column: In the Tabular View section uncheck "Allow individual item checkboxes".
  • Remove the "…": In the Columns section uncheck "Name (linked to document with edit menu)" and checkmark "Name (linked to document)".
  • Remove the hyperlink: In the Columns section uncheck "Name (linked to document with edit menu)" and checkmark "Name (for use in forms)".
  • Remove any unneeded columns such as Modified or Modified By.

image

 

Steps:

  • Add your web part for the list or library to a page.
  • For a minimal look set the web part's Toolbar Type property to “No Toolbar”.
  • Copy the JavaScript below to a Notepad file (name it something like “HideHeading.html”) and upload this file to a library such as Site Assets.
  • In the library where you uploaded this file, click the "…" and copy the displayed URL. It should look something like this:
        https://yourServerDomain/sites/training/SiteAssets/HideColumnHeadings.html
  • Below your list / library web part add a Content Editor Web Part (CEWP).
    • If the CEWP displays it’s title bar then in the Appearance section set the Chrome to “none”.
    • Paste the URL copied above into the Content Link box.
    • In the web part properties editor, click OK.
    • In the PAGE ribbon, click Save.
  • Or (for SharePoint view pages)
    • Edit the view page in SharePoint Designer 2013. 
    • Copy and paste the Javascript to just before the end tag for PlaceHolderMain (just before </asp:Content>).
  • If you want to hide the column headings of multiple web parts modify the IF statement like this Three web parts

Web part summary name!

In SharePoint 2007, the summary name is usually just the list’s name: “Shared Documents”.

In SharePoint 2010, the summary name is usually the list’s name PLUS the list’s description. For example the default for Shared Documents is: “Shared Documents Share a document with the team by adding it to this document library.”  (including the period)

To find the correct name use your browser’s View Source option to display the HTML of the page and search for “summary=” and copy the text that follows. Or, use the browser's developer tools (usually F12) and search for "summary="

    <table  …  summary="Shared Documents Share a document with the team by adding it to this document library."   … >

 

The JavaScript

Need to change multiple web parts? Edit the line that contains "if (x[i].summary==""

Two web parts:
             if (x[i].summary=="Tasks" | x[i].summary=="Shared Documents"
Three web parts:
             if (x[i].summary=="Tasks" | x[i].summary=="Links" | x[i].summary=="Shared Documents"

<script type="text/javascript">
// CEWP trick from techtrainingnotes.blogspot.com!

// techtrainingnotes.blogspot.com/2015/07/sharepoint-hide-list-and-library-column.html
// Hide column headings in web parts

function TTNHideHeadings()
{
  //Find the list  (change "Documents" to your web part's "summary" name)
  var x = document.getElementsByTagName("TABLE"); // find all of the Tables 
  var y;
  for (var i=0;i<x.length;i++) 
  {
    if (x[i].summary=="Documents")  //find the table with this name
    {
      y = x[i].getElementsByTagName("TR");
      y[0].style.display="none";  //hide the first row
    } 
  }
}

try {
  // for 2010 and 2013
  ExecuteOrDelayUntilScriptLoaded( TTNHideHeadings, "sp.js" );
}
catch (e) {
  // for 2007
  _spBodyOnLoadFunctionNames.push('TTNHideHeadings');
}
  
</script>

6/16/2015

SharePoint 2013: Create a Quote of the Day Web Part (a CEWP trick!)

(Updated 11/24/17 to allow use in a Publishing page.)

This is a 2013 version of the 2007 and 2010 article found here: http://techtrainingnotes.blogspot.com/2010/10/sharepoint-create-quote-of-day-web-part.html


Quote of the Day / Tip of the Day

Want to display some “wise words” for your coworkers? You need a Quote of the Day web part!

image

You could display a picture or product of the day:

image


This web part is another simple Content Query Web Part solution similar to the ones found in my SharePoint 2010 Customization book. But… this one is for 2013!

  • Works from a normal SharePoint list.
  • Displays a random quote from the list.
  • Can display a new quote on each page view, or just one new quote a day.
  • Can be used to display quotes, product announcements or any kind of text, pictures or other content that you can add to a SharePoint rich text editor column.


Create the Quotes list

While you could use a Custom List, I used an Announcements list as it already had what I needed, a Title field and a Rich Text field.

  1. Go to Settings (gear) and click Add an App.
  2. Find and click Announcements.
  3. Add a name for the list such as “Quotes”.
  4. The description is optional, but is best left blank as it adds a little complication later on.  (I.e., don't click Advanced Options and add a description!)
  5. Click Create.
  6. If you are not using the Announcements list type then from the list’s Settings menu click Create Column and add a “Multiple Lines of Text” column. Name the column “Quote” (although any name will work) and click “Rich text (Bold, italics, text alignment).
  7. Add a few quotes by clicking "new announcement" or New from the ITEMs ribbon. You can use all of the rich text formatting options if you like. (Bold, colors, etc.)
  8. Create a new view by clicking the Create View link in the LIST ribbon.
  9. Create the view as a Standard view and name it something like “QuoteView”. Un-checkmark all columns except for “Quote” column (the “Body” column if using an announcements list).
  10. Expand the Tabular View section (scroll down to find it) and uncheck "Allow individual item checkboxes".
  11. Click OK.

You now have the list that will store the quotes. You will now add two web parts to a page. One which is the list of quotes, and the other which is a Content Editor Web Part with the JavaScript and HTML code.


Add the Quotes list web part to the page

  1. Go to the page where you want to add the “Quote of the Day”, most likely your home page. 
  2. Click Settings (gear), Edit Page.
  3. Click where you would like to add the quotes.
  4. In the INSERT ribbon click Web Part and add the web part for the quotes list.
  5. In the web part click dropdown arrow and then Edit Web Part.
  6. Select the view you created above (“QuoteView”).
  7. Click OK.

This web part will be hidden when the JavaScript runs.


The JavaScript and HTML file

  1. Open Notepad or your favorite HTML editor.
  2. Copy the sample code from below and paste into your editor.
  3. Either delete my sample <style> block (it displays the quote in red) or customize your own style.
  4. Find the line with "var quotesWebPartName=" and change "Quotes" to your list's name.
  5. (Optional) Find the line with "var OneQuotePerVisit = false" and change it to true so the user can only see one quote per day.
  6. Save the file.
  7. Upload the file to a library where all of your users have at least Read or View access. "Site Assets" is a good choice.
  8. Find the URL of the uploaded file by clicking the "…" next to the file name. Copy the URL so we can paste it into the CEWP below.


The Content Editor Web Part

  1. Add a Content Editor Web Part (CEWP) and move it so it is near the quotes web part. While the list web part can go anywhere, the CEWP must go where you would like to display the quote of the day. 
  2. Click the CEWP’s dropdown menu and select Edit Web Part.
  3. Paste the URL you copied earlier into the Content Link box.
  4. In the Appearance section add a title for the web part (perhaps “Quote of the Day”).
  5. At the bottom of the web part properties box click OK.
  6. Save your page and test! Refresh the page to see if the quote changes.



The JavaScript

Copy and paste the following JavaScript into Notepad or your favorite HTML editor. (see above)

<!-- add your own formatting here... (optional)-->
<style type='text/css'>
  #TTNQuoteText { color:red }
</style>


<!-- Quote will be displayed here -->
<span id="TTNQuoteText"></span>



<script type="text/javascript">

function TTNShowQuote()
{
// another CEWP trick from http://TechTrainingNotes.blogspot.com
// http://techtrainingnotes.blogspot.com/2010/10/sharepoint-create-quote-of-day-web-part.html

// name of the quotes library web part
  var quotesWebPartName="Quotes"; 


// set this to "true" so the user will see the same quote 
// for 12 hours or until they close and reopen the browser
  var OneQuotePerVisit = false;



// don't change these
  var QuoteList;
  var QuoteArray = [];
  var quoteCount = 0;

  var TTNTables = document.getElementsByTagName("TABLE");
  var i=0;
  for (i=0;i<TTNTables.length;i++) 
  {
    if (TTNTables[i].summary)
    {
    if (TTNTables[i].summary == quotesWebPartName)
    {
      // Get the table with the quotes
      QuoteList = TTNTables[i].getElementsByTagName("tbody")[0];

      // hide the links list web part, but only if not in edit mode
// 11/25/17 update to allow use in a Publishing page.
if ( typeof PageState == 'undefined' || (PageState.ViewModeIsEdit != "1") )
{ QuoteList.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.style.display="none"; } break; } } } if (!QuoteList) { document.getElementById("TTNQuoteText").innerHTML="Web Part '" + quotesWebPartName + "' not found!"; } //Count the quotes var links = QuoteList.getElementsByTagName("TR") // find all of the rows var url; var quoteCount = 0; for (i=0;i<links.length;i++) { //if (links[i].childNodes[0].className=="ms-vb2") //{ QuoteArray[quoteCount] = i; quoteCount++; //} } if (quoteCount==0) { document.getElementById("TTNQuoteText").innerHTML="No quotes found in web part '" + quotesWebPartName + "'!"; } var id=-1; // check for a cookie and use last ID if found if (OneQuotePerVisit) { // check for a cookie with the last quote ID if (document.cookie.length>0) { c_start=document.cookie.indexOf("LastQuoteDisplayedID="); if (c_start!=-1) { c_start=c_start + "LastQuoteDisplayedID".length+1; c_end=document.cookie.indexOf(";",c_start); if (c_end==-1) c_end=document.cookie.length; id = unescape(document.cookie.substring(c_start,c_end)); } } } if (id == -1) { // generate a random quote ID id = Math.floor(Math.random() * QuoteArray.length) } // display the quote document.getElementById("TTNQuoteText").innerHTML= QuoteList.getElementsByTagName("TR")[QuoteArray[id]].childNodes[0].childNodes[0].childNodes[0].innerHTML; if (OneQuotePerVisit) { // set a cookie so they see the same quote for xx hours (.5 = 1/2 day = 12 hours) var exdate = new Date(); exdate.setDate(exdate.getDate() + 1); document.cookie="LastQuoteDisplayedID=" + id //+ ";expires=" + exdate.toUTCString(); } } // add our function to the SharePoint OnLoad event _spBodyOnLoadFunctionNames.push("TTNShowQuote"); </script>


Only have about 100 more of these to update from 2007/2010 to 2013!



.

Note to spammers!

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.