Customize SharePoint UI using JavaScript

As a best practice, Microsoft recommends us to avoid customizing the SharePoint farm to achieve our business logic and functionality. Using the app model is a step towards this goal. The patterns and practices gives us guidance on how to achieve some of the functionality we used to do with farm solutions.

Today, lets see how to customize SharePoint UI using JavaScript

I tried the Microsoft patterns and practices project Core.EmbedJavaScript . However, since it was created with a different visual studio version, it converted the project and loaded. But when I tried to run the project, it gave a Global.asax error as follows:

So, I’ll share my findings on how you can create the app from scratch.

Create a default provider hosted app in visual studio. Check out my post Provider Hosted App on how to do this.

Open the AppManifest.xml and click on the permissions tab. Select Scope as Web and give the FullControl permission.

Add the usings

using Microsoft.SharePoint.Client;
using System;
using System.Linq;
using System.Text;

Add two buttons to the default.aspx for adding and removing the customization.

<asp:Button ID="addCustomization" runat="server" Text="Add Customization" OnClick="addCustomization_Click" />
<asp:Button ID="removeCustomization" runat="server" Text="Remove Customization" OnClick="removeCustomization_Click" />

In the addCustomization_Click event handler add the following code. This will get the host web context and and call the AddJsLink method.

var spContext = SharePointContextProvider.Current.GetSharePointContext(Context);
using (var ctx = spContext.CreateUserClientContextForSPHost())
{
AddJsLink(ctx, ctx.Web);
}

The AddJsLink method builds the Scripts folder url. Then, it extends by adding the customization JavaScript file to the source url. In our case it is the ‘customization.js’. Then we go on to get the ID of the <head> tag and insert the script tag with the source url which we have built.

The web object has a collection UserCustomActions. We loop through the collection, check the Description and Location to see if it is the action we have added, and remove all the actions we have added previously. Then, create a new action, set the properties and add to the UserCustomActions collection.

public void AddJsLink(ClientContext ctx, Web web)
{
string scenarioUrl = String.Format("{0}://{1}:{2}/Scripts", this.Request.Url.Scheme,
this.Request.Url.DnsSafeHost, this.Request.Url.Port);
string revision = Guid.NewGuid().ToString().Replace("-", "");
string jsLink = string.Format("{0}/{1}?rev={2}", scenarioUrl, "customization.js", revision);

StringBuilder scripts = new StringBuilder(@"
var headID = document.getElementsByTagName('head')[0];
var");

scripts.AppendFormat(@"
newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = '{0}';
headID.appendChild(newScript);", jsLink);
string scriptBlock = scripts.ToString();

var existingActions = web.UserCustomActions;
ctx.Load(existingActions);
ctx.ExecuteQuery();
var actions = existingActions.ToArray();
foreach (var action in actions)
{
if (action.Description == "customization" &&
action.Location == "ScriptLink")
{
action.DeleteObject();
ctx.ExecuteQuery();
}
}

var newAction = existingActions.Add();
newAction.Description = "customization";
newAction.Location = "ScriptLink";

newAction.ScriptBlock = scriptBlock;
newAction.Update();
ctx.Load(web, s => s.UserCustomActions);
ctx.ExecuteQuery();
}

Inside the ‘customization.js’, we can add whatever customization we want for the host web. In our case we are adding a ribbon message and removing the ‘new subsite’ button in the bottom of the Site Contents page.

We are using the SP.UI.Status.addStatus method to show the status message. You can check out all the available operations you can do with the status bar at SP.UI.Status.

The contents of  ‘customization.js’ is listed below.

var jQuery = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.2.min.js";

// Is MDS enabled?
if ("undefined" != typeof g_MinimalDownload && g_MinimalDownload && (window.location.pathname.toLowerCase()).endsWith("/_layouts/15/start.aspx") && "undefined" != typeof asyncDeltaManager) {
// Register script for MDS if possible
RegisterModuleInit("customization.js", JavaScript_Embed); //MDS registration
JavaScript_Embed(); //non MDS run
} else {
JavaScript_Embed();
}

function JavaScript_Embed() {

loadScript(jQuery, function () {
$(document).ready(function () {
var message = "<img src='/_Layouts/Images/STS_ListItem_43216.gif' align='absmiddle'> <font color='#AA0000'>JavaScript customization is <i>fun</i>!</font>"

// Execute status setter only after SP.JS has been loaded
SP.SOD.executeOrDelayUntilScriptLoaded(function () { SetStatusBar(message); }, 'sp.js');

// Customize the viewlsts.aspx page
if (IsOnPage("viewlsts.aspx")) {
//hide the subsites link on the viewlsts.aspx page
$("#createnewsite").parent().hide();
}
});
});
}

function SetStatusBar(message) {
var strStatusID = SP.UI.Status.addStatus("Information : ", message, true);
SP.UI.Status.setStatusPriColor(strStatusID, "yellow");
}

function IsOnPage(pageName) {
if (window.location.href.toLowerCase().indexOf(pageName.toLowerCase()) > -1) {
return true;
} else {
return false;
}
}

function loadScript(url, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = url;

// Attach handlers for all browsers
var done = false;
script.onload = script.onreadystatechange = function () {
if (!done && (!this.readyState
|| this.readyState == "loaded"
|| this.readyState == "complete")) {
done = true;

// Continue your code
callback();

// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};

head.appendChild(script);
}

Download the full source code from CustomizeSPUsingJS

Related posts: SharePoint hosted apps

Leave a Reply

Your email address will not be published. Required fields are marked *