September 8, 2016

Injecting Javascript file through SharePoint Hosted App

A requirement came across was to execute a JavaScript on all the pages of SharePoint Site. Here, option of achieving the functionality by developing custom master page was eliminated as we were dealing with a SharePoint Hosted App. It is also easy to achieve through server side but need to find solution on client side as SharePoint Hosted App has everything on client side. Finally, we found a solution to inject the JavaScript using Custom Action.

JavaScript Object Model (JSOM) allows us to programmatically register Custom Action with Host Web in a way similar to declarative approach used with Farm or Sandboxed Solution. In order to register a Custom Action using JSOM, your app requires the Full Control permission on the Site/Site Collection where you want to register it.

To achieve this, we need to perform two steps as below:
  1. Provisioning the JavaScript file from App web to Host web
  2. Registering the Custom action with the file path referring to that JavaScript file in the Host web.

1. Provisioning the JavaScript file from app web to host web:

function uploadFileToHostWebViaCSOM(serverRelativeUrl, filename, contents) {      
        var executor = new SP.RequestExecutor(window.appWebUrl);
        executor.executeAsync(
                {
                    url: window.appWebUrl + "/_api/SP.AppContextSite(@target)/web/GetFolderByServerRelativeUrl('" + serverRelativeUrl + "')/Files?@target='" + window.hostWebUrl + "'",
                    method: "GET",
                    headers: { "Accept": "application/json; odata=verbose" },
                    success: function (data) {
                        var jsonObject = JSON.parse(data.body);
                        var createInfo = new SP.FileCreationInformation();
                        createInfo.set_content(new SP.Base64EncodedByteArray());
                        for (var i = 0; i < contents.length; i++) {
                            createInfo.get_content().append(contents.charCodeAt(i));
                        }
                       createInfo.set_url(filename);
                       createInfo.set_overwrite(true);
                       var files = hostWebContext.get_web().getFolderByServerRelativeUrl(serverRelativeUrl).get_files();
                       var isexist = false;
                        jsonObject.d.results.forEach(function (item, index) {
                            if (item.Name == filename)
                                isexist = true;
                        });
                        if (isexist)
                            files.getByUrl(filename).checkOut();
                        var file = files.add(createInfo);
                        file.checkIn('Add-in deployment.');
                        file.publish('Add-in deployment.');

                        appWebContext.load(file);
                        appWebContext.executeQueryAsync(success, function (sender, args) {
                            alert(args.get_message());
                        });
                    },
                    error: function (data, errorCode, errorMessage) {
                        console.log("error");
                    }
                });
    };


Here, we are first fetching the file from app web and checking that whether it exists in host web or not. If the file exists then we will update the existing file, check in and publish it. If the file does not exist then we just add the file, check in and publish it.

2. Registering the custom action with the file path:

var context = web.get_context();
var webs = web.get_webs();
var actions = web.get_userCustomActions();
context.load(actions);
context.load(webs, 'Include(Title,Webs)');
context.executeQueryAsync(function () {

  var newAction = actions.add();
  // the 'description' is what we'll use to uniquely identify our custom action
  newAction.set_description(actionDescription);
  newAction.set_location('ScriptLink');
  newAction.set_scriptBlock(getScripts(window.hostWebUrl + '/Style Library/EasyNav/Scripts/tinysort.min.js'));
  newAction.set_sequence(1004);
  newAction.update();

  context.executeQueryAsync(function () { }, fail);
}, fail);

The above code adds a custom action on a web object in Host web. Wherein,
set_location specifies it is a script registration action,
set_scriptBlock indicates the JavaScript file's path in host web,
set_sequence specifies the sequence in which the files are to be loaded if there is more than one.

Once above code will be executed through custom action, we can see all JavaScript files loaded on all the pages of the SharePoint Site.

If you have any questions you can reach out our SharePoint Consulting team here.

No comments:

Post a Comment