Introduction

SharePoint 2013 introduces a new feature “Minimal Download Strategy” or “MDS” to improve the page performance. MDS is a technology which allows SharePoint sites to download and render pages more efficiently and effectively by loading only the parts on the page which needs to be updated based on user’s request.

For instance, when navigating from one page to another on the site, only content area and left navigation bar get refreshed while the header, footer, and top bar do not re-render which results in faster page load.

Quick points to note regarding MDS feature:

  • Improves page performance by refreshing only partial page, and thus ensures smooth user experience
  • MDS feature uses an application page' _layouts/15/start.aspx' and a JavaScript file '_layouts/15/start.js'. These files determine the requested URL and instructions for loading the page changes. During the navigation from one page to another, these files download only the changes between two pages.
  • By default, MDS feature is enabled on SharePoint 2013 sites. To enable/ disable this feature, go to Site Settings -> Manage Site Features -> Activate/ Deactivate Minimal download Strategy feature.

Let’s understand this with the help of an example.

Scenario

To further understand how the customizations can be done on MDS enabled sites, let’s consider the below scenario:

On a team site, we have a requirement to add a footer component below the left navigation menu. The footer component will display some site properties like External Sharing status and Current user’s access on the site (as shown in the screenshot below).

Solution/ Code Snippet

Javascript Code:

Save the code in js file with the name "mdscustom.js" and upload on your SharePoint site. Here is the javascript code to display the properties below the left navigation menu:

001.Type.registerNamespace("MDSCustomjs"); //Register the namespace for your custom script
002.MDSCustomjs = (typeof MDSCustomjs != "undefined") ? MDSCustomjs : {};
003. 
004. // variable declarations
005.var CONST_ROLE_MANAGER = 'Manager';
006.var CONST_ROLE_MEMBER = 'Member';
007.var CONST_ROLE_VISITOR = 'Visitor';
008.var CONST_ROLE_RESTRICTED = 'Restricted';
009.var CONST_EXTERNALSHARE_NO = 'No';
010.var CONST_EXTERNALSHARE_YES = 'Yes';
011.var CONST_SITE_URL = '';
012. 
013. // Method to get  site external sharing details and bind in footer div
014.MDSCustomjs.getSiteDetails = function (access) {         
015.       
016.            $.ajax({
017.                url: CONST_SITE_URL + "/_api/site",
018.                method: "GET",
019.                headers: { "Accept": "application/json; odata=verbose" },
020.                success: function (data) {
021.                    var shared = CONST_EXTERNALSHARE_NO;
022.                    if (data.d.ShareByEmailEnabled) {
023.                        shared = CONST_EXTERNALSHARE_YES;
024.                    }    
025.                     
026.                    $('#footer').empty();
027.                    $('#footer').append('<hr/><div><label for="access" id="lblAccess">Your access : ' + access + '</label></div>');
028.                    $('#footer').append('<div>External Sharing : <label for="ExternalSharing" id="lblexternalShared">' + shared + '</label></div>');
029.                },
030.                error: function (data) { 
031.                    console.log(data);
032.                }
033.            });
034.}
035. // Method to get logged in user's access
036.MDSCustomjs.getCurrentUserGroupColl = function (UserID) {
037.     
038.        $.ajax({
039.            url: CONST_SITE_URL + "/_api/web/GetUserById(" + UserID + ")/Groups",
040.            method: "GET",
041.            headers: { "Accept": "application/json; odata=verbose" },
042.            success: function (data) {
043. 
044.                var results = data.d.results; var InnrHtmlgrp = "<ul>";
045.                for (var i = 0; i < results.length; i++) {
046.                    InnrHtmlgrp += "<li>" + results[i].Title + "</li>";
047.                }
048.                var access = '';
049.                if ((InnrHtmlgrp.indexOf("Owners") > -1)) {
050.                    access = CONST_ROLE_MANAGER;
051. 
052.                }
053.                else if ((InnrHtmlgrp.indexOf("Members") > -1)) {
054.                    access = CONST_ROLE_MEMBER;
055.                }
056.                else if ((InnrHtmlgrp.indexOf("Visitors") > -1)) {
057.                    access = CONST_ROLE_VISITOR;
058.                }
059.                else {
060.                    access = CONST_ROLE_RESTRICTED;
061.                }               
062.                MDSCustomjs.getSiteDetails(access);
063. 
064.            }, error: function (data) {
065.                console.log(data);
066.            }
067.        });
068.     
069.}
070. 
071. 
072. // Method to get details of current user
073.MDSCustomjs.getCurrentUser = function () {
074.    CONST_SITE_URL = _spPageContextInfo.webAbsoluteUrl;
075.        $.ajax({
076.            url: CONST_SITE_URL + "/_api/web/CurrentUser",
077.            method: "GET",
078.            headers: { "Accept": "application/json; odata=verbose" },
079.            success: function (data) {              
080.                
081.                    MDSCustomjs.getCurrentUserGroupColl(data.d.Id);
082.                
083.            },
084.            error: function (data) {
085.                console.log(data);
086.            }
087.        });   
088.}
089. 
090. // Call custom methods on page load
091.MDSCustomjs.Script_Inject = function () {
092.    $(document).ready(function () {
093.        SP.SOD.executeOrDelayUntilScriptLoaded(function () { MDSCustomjs.getCurrentUser(); }, 'sp.js');
094.    }); 
095.}
096. 
097. // Checking whether MDS is enabled on the site or not
098.if ("undefined" != typeof g_MinimalDownload && g_MinimalDownload && (window.location.pathname.toLowerCase()).endsWith("/_layouts/15/start.aspx") && "undefined" != typeof asyncDeltaManager) {
099. 
100.    var url = window.location.href.split("/");
101.           // 
102.    var thisUrl = "https://" + url[2] + "<your location of javascript file>";
103.    RegisterModuleInit(thisUrl, MDSCustomjs.getCurrentUser);
104. 
105.    MDSCustomjs.Script_Inject();
106.} else {
107.    MDSCustomjs.Script_Inject();
108.}
Master Page Code:

Include the following javascript files in the <head> section of your custom master page.

<SharePoint:ScriptLink ID="js1" language="javascript"  name="https://testing.sharepoint.com/SiteAssets/js/jquery-1.9.1.min.js" OnDemand="false" LoadAfterUI="true" runat="server" Localizable="false" />
 
<SharePoint:ScriptLink ID="js2" language="javascript"  name="/_layouts/15/sp.runtime.js" OnDemand="false"  LoadAfterUI="true" runat="server" Localizable="false" />
 
<SharePoint:ScriptLink ID="js3" language="javascript"  name="/_layouts/15/sp.js" OnDemand="false" LoadAfterUI="true" runat="server" Localizable="false" />


Add div to your masterpage after </SharePoint:SPNavigationManager> tag:

<div id="footer"></div>

Now, include your custom "mdscustom.js" file just above </body> tag.

<SharePoint:ScriptLink language="javascript" name="https:///mdscustom.js" OnDemand="false" LoadAfterUI="true" runat="server" Localizable="false"/>


In the same way, as per the requirements, custom methods can be developed and called to get further site properties and you can bind them to the footer component.