If you need to inject custom javascript file to all pages in all sub sites in Sharepoint site collection you may edit site master page and system master page and add appropriate <script> tag there. However if you have many site collections or if your site collections don’t use publishing feature it may not be very convenient. There is another way to add custom javascript to all pages: site collection’s custom actions (SPSite.UserCustomActions) with ScriptLink location. Here is PowerShell script which can be used in order to add custom action to each site collection in specified web application with custom javascript reference:
1: param(
2: [string]$url
3: )
4:
5: function Add-Custom-Action($site, $actionUrl, $sequence)
6: {
7: Write-Host "Add custom action $actionUrl on" $site.Url -foregroundcolor green
8: $actions = $site.UserCustomActions
9: $contains = $false
10: foreach ($a in $actions)
11: {
12: if ($a.ScriptSrc.ToLower() -eq $actionUrl.ToLower())
13: {
14: $contains = $true
15: break
16: }
17: }
18:
19: if ($contains)
20: {
21: Write-Host " Custom action is already added" -foregroundcolor yellow
22: return
23: }
24:
25: $action = $site.UserCustomActions.Add()
26: $action.Location = "ScriptLink"
27: $action.ScriptSrc = $actionUrl
28: $action.Sequence = $sequence
29: $action.Update()
30: }
31:
32: Start-Transcript -Path "output.log" -Append -Force -Confirm:$false
33:
34: if (-not $url)
35: {
36: Write-Host "Specify web app url in url parameter" -foregroundcolor red
37: return
38: }
39:
40: $webApp = Get-SPWebApplication $url
41: $webApp.Sites | ForEach-Object { Add-Custom-Action $_ "/_layouts/15/test/foo.js" 10001 }
42:
43: Stop-Transcript
This script goes through all site collections and adds custom action to each of them. Before to add custom action it checks whether action with specified url is already added and if yes, skips current site collection, so it is safe to call this script many times for the same web app (always create your script with assumption that they may be executed many times for the same site). As result you will have your custom javascript available in all pages in all sub sites in all site collections, including list forms and application layouts pages.
Please note that this script uses basic Sharepoint object model and can be used with on-premise Sharepoint site only. In future posts I will show how to do the same using client object model which can be used in Sharepoint Online.
Update 2016-01-24: see Add custom javascript file to all pages in Sharepoint Online site collection for example of similar script for Sharepoint Online.
Hi,
ReplyDeleteI tried this but I cannot get the pages to load when using a ScriptSrc which is not beginning with ~siteCollection like "/Style Library/myLib.js" or "http://myserver.com/Style Library/myLib.js". Do you have an idea? Also put this on SO: http://sharepoint.stackexchange.com/questions/204017/cannotmakebrowsercachesafelayoutsurl-for-scriptlink-in-customaction
hi Ben,
ReplyDeletesome time ago I also faced with similar strange issue: looks like Sharepoint somehow checks that file referenced in ScriptSrc really exists. If file not found, pages got broken. In example in this post I used js file from /_layouts subfolder, which as you probably know can be opened in context of any Sharepoint site, i.e. suppose that http://example.com is root site of site collection and http://example.com/test is one of its sub sites, then we will have:
http://example.com/_layouts/15/test/foo.js
http://example.com/test/_layouts/15/test/foo.js
both files will be opened.
But when you try to add js file into Sharepoint doclib, e.g. to Style library, it will be accessible only by absolute url
http://example.com/Style library/foo.js.
So if you use relative url and try to open page on sub site it will try to find it on
http://example.com/test/Style library/foo.js
and won't find it here. That's why in last case ~sitecollection is needed.