Ashok Raja's Blog
Refer Scripts and CSS Style Sheet in SharePoint 2013 Visual Web Part and Master Page
by Ashok Raja T 20. October 2012 01:20

This article on how to refer JavaScript and CSS Style Sheet in SharePoint 2013 Visual Web Part and Master Page explains the different options available to refer JavaScript and Style Sheet with or without editing Master Page and also referring it from Visual Web Part.

To explain the different options I have created a sample Visual Studio 2012 SharePoint Solution which is available for download at the bottom of the post. In this solution I have included multiple js files which are referred via different channels and writes some content to the page to differentiate its reference pattern. I have also included multiple css files with different class names and have applied those styles in the Visual WebPart to differentiate the style reference.

Although this article is for SharePoint 2013, I have explained the difference between the approach in SharePoint 2010 and SharePoint 2013 and have also included a SharePoint 2010 sample for download.

The below is the screen shot of end result in a sub site of SharePoint 2013 team site.

SP 2013 Script Reference

Referring Java Script in Master Page

Referring script in master page can be done by editing or without editing the master page. If we would like to inject JavaScript file without editing the Master Page, the approach would require a delegate control or a custom action.

By Editing Master Page

If you have got the privilege to edit the Master Page, then referring script is an easy task. The below example refers jQuery from style library located in site collection root. The token ~sitecollection can be replaced with ~site if you would like to refer the scripts from the respective site’s style library. Add the below lines just above the closing tag of head tag in the Master Page to refer scripts.

<SharePoint:ScriptLink ID="ScriptLink1" Name="~SiteCollection/Style Library/Scripts/sitecol-master.js" runat="server" /> 
<SharePoint:ScriptLink ID="ScriptLink2" Name="~Site/Style Library/Scripts/site-master.js" runat="server" />

The above link can also be modified to refer scripts from 15 hive (C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15) . The below is the changed script targeting 15 layouts folder.

<SharePoint:ScriptLink ID="ScriptLink1" Name="~SiteCollection/_layouts/15/SFS.Ashok.Refer/Scripts/sitecol-master.js" runat="server" /> 
<SharePoint:ScriptLink ID="ScriptLink2" Name="~Site/_layouts/15/SFS.Ashok.Refer/Scripts/site-master.js" runat="server" />

Note : In case of SharePoint 2013 , the URL should contain 15 after layouts to point the virtual folder “ _layouts” but this is not required for SharePoint 2010, so the the code snippet for SharePoint 2010 would be like

<SharePoint:ScriptLink ID="ScriptLink1" Name="~SiteCollection/_layouts/SFS.Ashok.Refer/Scripts/sitecol-master.js" runat="server" /> 
<SharePoint:ScriptLink ID="ScriptLink2" Name="~Site/_layouts/SFS.Ashok.Refer/Scripts/site-master.js" runat="server" />

Without Editing Master page

JavaScript can be injected throughout the site without editing the Master Page in 2 methods. One is by creating a delegate control and another is by creating a custom action and hooking it to each and every page.

1. Custom Action

This method requires an element file to inject the script into site. The source JavaScript can be either manually placed in appropriate location in the SharePoint farm or it can be deployed through a Module. The Custom action accepts both ~sitecollection and ~site in referring the script. The location attribute in CustomAction element should be set as “ScriptLink” . The sequence number attribute in CustomAction element decides the order in which the script has to be loaded into the page

<SharePoint:ScriptLink ID="ScriptLink1" Name="~SiteCollection/_layouts/SFS.Ashok.Refer/Scripts/sitecol-master.js" runat="server" /> 
<SharePoint:ScriptLink ID="ScriptLink2" Name="~Site/_layouts/SFS.Ashok.Refer/Scripts/site-master.js" runat="server" />

2. Delegate Control

Delegate control is also one of the options to inject JavaScript into a Master Page without editing it. Every SharePoint Master Page contains a delegate control with control id AdditionalPageHead. The attribute AllowMultipleControls="true" allows multiple controls to be injected to this place holder rather than overwriting the existing content/control. This is the only delegate control which has this attribute by default set as true. This enables us to inject JavaScript or CSS into a Master Page without editing it.

Element File

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Control Id="AdditionalPageHead" Sequence="50" ControlSrc="~/_controltemplates/15/SFS.Ashok.Refer/Refer.ascx"  xmlns="http://schemas.microsoft.com/sharepoint/" />
</Elements>

Note : SharePoint 2010 does not require 14 to be included in its path. So in SharePoint 2010 , ControlSrc would point to "~/_controltemplates/SFS.Ashok.Refer/Refer.ascx"

Ascx File

<SharePoint:ScriptLink ID="ScriptLink1" Name="~SiteCollection/_layouts/15/SFS.Ashok.Refer/Scripts/sitecol-delegate.js" runat="server" />
<SharePoint:ScriptLink ID="ScriptLink2" Name="~Site/_layouts/15/SFS.Ashok.Refer/Scripts/site-delegate.js" runat="server" />

Referring JavaScript in Visual Web part

1. For Form Solution

Referring JavaScript is fairly strait forward in Visual Web Part. The Script Link is the best option to go for. The below is the code snippet to refer script in Visual Web Part.

<sharepoint:scriptlink runat="server" name="~SiteCollection/_layouts/15/SFS.Ashok.Refer/Scripts/sitecol-visualwp.js" > </sharepoint:scriptlink>
<sharepoint:scriptlink runat="server" name="~Site/_layouts/15/SFS.Ashok.Refer/Scripts/site-visualwp.js" > </sharepoint:scriptlink>

To test the code, I created a site collection named as RootWeb and sub site named SubWeb. The below piece of markup is rendered in the sub site SubWeb.

In SharePoint 2013 Script Link control generates the below mark up

<script src="/sites/RootWeb/_layouts/15/sfs.ashok.refer/scripts/sitecol-delegate.js"></script>
<script src="/sites/RootWeb/SubWeb1/_layouts/15/sfs.ashok.refer/scripts/site-delegate.js"></script>

In SharePoint 2010 Script Link control generates the below mark up

document.write('<script src="/sites/RootWeb/_layouts/sfs.ashok.refer/scripts/sitecol-delegate.js"></' + 'script>');

2. For SandBoxed WebPart

SandBoxed Visual Web Part does not support Scriptlink and cssregistration controls . The alternate option to refer scripts and stylesheet is via code. The below code snippet can be used to refer script in a SandBoxed Visual Web Part

 protected override void Render(System.Web.UI.HtmlTextWriter writer)
 {
     writer.Write(BindScript("/Style Library/Scripts/jquery.js", true));
     writer.Write(BindScript("/Style Library/Scripts/jquery.dataTables.min.js", true));
     base.Render(writer);
 }
 
 private string BindScript(string ScriptUrl, bool PickFromSiteCollection)
 {
     if (PickFromSiteCollection)
         ScriptUrl = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Site.RootWeb.Url, ScriptUrl);
     else
         ScriptUrl = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Web.Url, ScriptUrl);
 
     return string.Format(@"<script type=""text/javascript"" src=""{0}""></script>", ScriptUrl);
 }

Referring CSS Style Sheet in Master Page

By Editing Master Page

Style Sheets can be referred in Master Page by adding CssLink control in header section of Master Page. Find below the sample for adding Style Sheet reference directly in Master Page. Add the below code inside the head tag of Master Page.

<SharePoint:CssRegistration  ID="CssRegistration1" Name="<% $SPUrl:~SiteCollection/_layouts/15/SFS.Ashok.Refer/Styles/sitecol-master.css%>" runat="server" After="corev15.css" />
<SharePoint:CssRegistration  ID="CssRegistration2" Name="<% $SPUrl:~Site/_layouts/15/SFS.Ashok.Refer/Styles/site-master.css%>" runat="server" After="corev15.css" />

Note : For SharePoint 2010, change corev15.css to Corev4.css, if our custom CSS has to be loaded after Core CSS

Without Editing Master Page

The same methods applied for referring JavaScript is also applicable to refer Style Sheet.

1. Custom Action

The main difference between referencing JavaScript and CSS through custom action is the usage of ScriptBlock attribute. To refer JavaScript , we used ScriptSrc to refer the path of JavaScript. But to referrer a Style Sheet we will be using ScriptBlock attribute to render the reference link.

<CustomAction Id="ReferCssSiteCol" Location="ScriptLink" ScriptBlock="document.write('&lt;link rel=&quot;stylesheet&quot; After=&quot;Corev15.css&quot;  type=&quot;text/css&quot; href=&quot;../_layouts/15/SFS.Ashok.Refer/Styles/sitecol-customaction.css&quot;&gt;&lt;/' + 'link&gt;');" Sequence="202" />
<CustomAction Id="ReferCssSite" Location="ScriptLink" ScriptBlock="document.write('&lt;link rel=&quot;stylesheet&quot; After=&quot;Corev15.css&quot;  type=&quot;text/css&quot; href=&quot;../../_layouts/15/SFS.Ashok.Refer/Styles/site-customaction.css&quot;&gt;&lt;/' + 'link&gt;');" Sequence="203" />

2. Delegate Control

To refer CSS through delegate control add the below CSS Link in ascx file. In Script Link,  ~sitecollection or ~site token can be used as the part of js file path , but in cssregistration control , the entire path has to be referred via SPUrl:~SiteCollection or SPUrl:~Site

<SharePoint:CssRegistration  ID="CssRegistration1" Name="<% $SPUrl:~SiteCollection/_layouts/15/SFS.Ashok.Refer/Styles/sitecol-delegate.css%>" runat="server" After="corev15.css" />
<SharePoint:CssRegistration  ID="CssRegistration2" Name="<% $SPUrl:~Site/_layouts/15/SFS.Ashok.Refer/Styles/site-delegate.css%>" runat="server" After="corev15.css" />

Referring CSS Style Sheet in Visual Web Part

There is a major difference in referring CSS file in SharePoint 2010 visual web part and SharePoint 2013 visual web part. As far as SharePoint 2010 is concerned the same piece of code used in Master Page or delegate control can be used to refer CSS files.  But in SharePoint 2013, the visual web part , does not allow $SPUrl:~SiteCollection and $SPUrl:~Site tokens. Also, using HLML link element on ascx file of SharePoint 2013 Visual WebPart does not have any impact on out put.Still we can use CssRegistration control to refer styles without tokens, but ensure that its referred from appropriate base path ( site collection or site). Referring Style Sheet can also be achieved through C# code by overriding the render method of web part's render method. The below are some of the available options to refer style sheets

Note for Sand Boxed Solution : Site Token and SiteCollection token cannot be used in SandBox Web Part. Also, both ScriptLink and CssRegistration control cannot be used in SandBox WebPart. The easiest option to refer script files and style sheets is via server side code.

Option 1 - Referring CSS Style Sheet via code

 protected override void Render(System.Web.UI.HtmlTextWriter writer)
 {
     writer.Write(BindStyle("/Style Library/Styles/datatable.css", true));
     base.Render(writer);
 }
 
 private string BindStyle(string StyleUrl, bool PickFromSiteCollection)
 {
     if (PickFromSiteCollection)
         StyleUrl = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Site.RootWeb.Url, StyleUrl);
     else
         StyleUrl = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Web.Url, StyleUrl);
 
     return string.Format(@"<link rel=""stylesheet"" href=""{0}"" type=""text/css"" />", StyleUrl);
 }

Option 2 - Referring CSS Style Sheet via code

 protected override void Render(System.Web.UI.HtmlTextWriter writer)
 {
    base.Render(writer);
 
    RegisterCss(SPContext.Current.Site.RootWeb.Url + "/_layouts/15/SFS.Ashok.Refer/Styles/sitecol-visualwp.css", writer);
    RegisterCss(SPContext.Current.Web.Url + "/_layouts/15/SFS.Ashok.Refer/Styles/site-visualwp.css", writer);
 }
 
 private void RegisterCss(string StyleUrl, System.Web.UI.HtmlTextWriter writer)
 {
    StringBuilder StyleRef = new StringBuilder();
    StyleRef.AppendLine("var hd = document.getElementsByTagName(\"head\")[0];");
    StyleRef.AppendLine("if(document.createStyleSheet)");
    StyleRef.AppendLine("{");
    StyleRef.AppendLine(" document.createStyleSheet('" + StyleUrl + "');");
    StyleRef.AppendLine("} else {");
    StyleRef.AppendLine(" var lk = document.createElement('link');");
    StyleRef.AppendLine(" lk.type = 'text/css';");
    StyleRef.AppendLine(" lk.rel = 'stylesheet';");
    StyleRef.AppendLine(" lk.href = '" + StyleUrl + "';");
    StyleRef.AppendLine(" hd.appendChild(lk);");
    StyleRef.AppendLine("}");
    writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
    writer.RenderBeginTag(HtmlTextWriterTag.Script);
    writer.WriteLine(StyleRef.ToString());
    writer.RenderEndTag();
 }

The above C# code in-turn injects the below piece of JavaScript code into the page to refer CSS

 <script type="text/javascript">
 	var hd = document.getElementsByTagName("head")[0];
 	if(document.createStyleSheet)
 	{
 	 document.createStyleSheet('http://win2k12:901/sites/RootWeb/SubWeb1/_layouts/15/SFS.Ashok.Refer/Styles/site-visualwp.css');
 	} else {
 	 var lk = document.createElement('link');
 	 lk.type = 'text/css';
 	 lk.rel = 'stylesheet';
 	 lk.href = 'http://win2k12:901/sites/RootWeb/SubWeb1/_layouts/15/SFS.Ashok.Refer/Styles/site-visualwp.css';
 	 hd.appendChild(lk);
 	}
 </script>

Option 3 – Referring CSS Style via CssRegistration Control ( Applicable only for Form Solutions)

The below code can be directly placed in ascx file. Change the Name attribute accordingly to locate the base path (site or sitecollection) from which the the file has to be picked up.

<SharePoint:CssRegistration ID="CssRegistration1" Name="/_layouts/15/SFS.Ashok.Refer/Styles/site-visualwp.css" runat="server" After="corev15.css" />

Update on 2013 June 20 : Checkout my Script Box Webart, which provides an easy option to refer scripts and css in SharePoint Application

Downloads

blog comments powered by Disqus