Nov 30, 2016

Easily extend SharePoint - "Open in a new tab" with JS & PnP PowerShell

Extend SharePoint capabilities easily with simple JS snippets

Sometimes, a useful SharePoint extension does not need any server-side code. In these cases, a simple JS snippet is sufficient. To demonstrate an easy way to deploy SharePoint customizations, I will take a really simple case but quite useful for end-users. from latter upgrades of SharePoint 2013, right-click on the name of a file (in default views) pops up the Edit Control Block. Which is pretty intuitive but has the serious drawback of overriding the standard browser right-click menu, and a particular interesting feature frequently asked. As a SharePoint consultant, I often hear from my customers :

"I don't want this file to open in-place in my current browser window, can't I have a 'Open in new tab' link as I have it everywhere else with my browser ?"

There is a convenient way to achieve that, Add this link in the ECB menu. This must be done through custom actions. Wait..., you mean I have to deploy a WSP to have that single link ?

Of course not! Just deploy it through CSOM !

Hopefully, you won't have to code and compile a .NET application for that, the SharePoint

PnP Community already ships a set of PowerShell cmdlets that allows to do all the tricks

You can find all the source code on GitHub and even an installer to set up all the cmdlets on your workstation

What do we have to do ?

  1. Provision a JS file on the SharePoint that contains all the needed code
  2. Add a script link custom action to the site collection that makes all the pages of the site collection references our script file
  3. Add the proper custom action in the Edit Control Block that calls our JS function

The (very complex) code

var YPCode = YPCode || {}; 
YPCode.Utils = YPCode.Utils || {}; 
YPCode.Utils.openInNewTab = function (url) { 
  var win = window.open(url, '_blank'); 
  if (win) 
    win.focus(); 
}; 

It opens the specified URL in a new window (a new tab) and focuses on that tab

The PnP cmdlets used here :

  • Add-PnPFile to provision the .js file
  • Add-PnPJavaScriptLink to reference our JS file in every pages of the site collection (can also be scoped to a single web)
  • Add-PnPCustomAction to provision the custom action to all lists (by its definition type id)

Our own customization cmdlet

[CmdletBinding()] 
Param ( 
  [Parameter(Mandatory=$True, HelpMessage="The site collection relative URL of the site assets library (without the starting /)")]
  [string]$SiteAssetsUrl,
  [Parameter(Mandatory=$False)] 
  [int]$ListBaseTemplate=101,
  [Parameter(Mandatory=$False)]
  [string]$JsFileName ) 
  # Default values 
  $defaultJsFileName = "openInNewTab.js" 
  $defaultScriptLinkName = "SLOpenInNewTab" 
  $defaultCustomActionName = "OpenInNewTabCustomAction" 
  $defaultCustomActionTitle = "Open in a new Tab" 
  $defaultCustomActionDescription = "Allows to open a document in a new tab" 
  
  # Create the context if not already existing 
  Try { Get-PnPContext } 
  Catch { Write-Host "Please connect to SharePoint" Connect-PnPOnline } 
  
  If (!$JsFileName) { 
    $JsFileName = $defaultJsFileName 
  } 
  
  # Write the needed JavaScript in a local file 
  $js = "var YPCode = YPCode || {}; YPCode.Utils = YPCode.Utils || {}; YPCode.Utils.openInNewTab = function (url) { var win = window.open(url, '_blank'); if (win) win.focus(); };" 
  $js | Out-File $JsFileName 
  
  # Get the web URL 
  $siteCollUrl = (Get-PnPSite).Url 
  # Upload the JS file 
  Try { 
    $provisionnedFile = Add-PnPFile -Path $JsFileName -Folder $SiteAssetsUrl 
  } 
  Catch { 
    Write-Host The JavaScript file $JsFileName cannot be provisionned to $SiteAssetsUrl 
    Return 
  } 
  
  Try { 
    # Add the script link custom action 
    $jsFileUrl = $siteCollUrl + "/" + $SiteAssetsUrl + "/" + $JsFileName 
    $result = Add-PnPJavaScriptLink -Name $defaultScriptLinkName -Scope Site -Url $jsFileUrl 
    # Add the custom action 
    $result = Add-PnPCustomAction -Name $defaultCustomActionName -Title $defaultCustomActionTitle -Description $defaultCustomActionDescription -RegistrationId $ListBaseTemplate -RegistrationType "List" -Group "SiteActions" -Location "EditControlBlock"  -Url "javascript:YPCode.Utils.openInNewTab('{ItemUrl}');" -Scope Site 
  } Catch { 
    Write-Host The custom actions cannot be added to the target site 
  } 

Execute this powershell command and that's it! You have implemented a simple customization to SharePoint.

The advantages:

  • No solution package deployment (no downtime, no need for maintenance window)
  • Done using CSOM (remotely), you can execute this command from any host able to reach your SharePoint site
  • As valid On-Premises as Online

You can now reuse this technique to deploy any customizations implemented in JavaScript (simple or more complex ones).

I hope it will give you ideas for your future customizations.

See you soon!

Yannick

Other posts