Category Archives: SharePoint 2013

Form Validation and Custom Save Functionality in the Standard SharePoint List Form

Interactive Business Systems is now Planet Technology. Looking for a new job? We work with some of the biggest names in tech, and we’re hiring! Check out our open jobs and make your next career move with Planet.


I have a client that needs to log any interactions with their customers in SharePoint.  This client is proficient enough with SharePoint that they feel perfectly comfortable modifying lists in order to add or remove fields to accommodate their needs without having to go through us.  They are regularly adding new fields to this log list in order to capture some new piece of relevant information that it was decided they needed.  This is important background because when they approached me to create a way for them to generate multiple log entries from one “New Item” SharePoint List Form, I knew I couldn’t just create a custom “New Item” form to accomplish this or they would lose the ability to add new fields without having to either modify this custom “New Item” form, or involve us to make those modifications.

So I had to come up with a solution that would retain the standard “New Item” form (so any fields added/removed from the list would be reflected in the form) but would allow for the user to create an entry in their logs for every customer selected in the form.

Read more

Inject Scripts in SharePoint with JavaScript

Interactive Business Systems is now Planet Technology. Looking for a new job? We work with some of the biggest names in tech, and we’re hiring! Check out our open jobs and make your next career move with Planet.


Don’t worry, it’s the good kind of Script Injection!

I was recently working in a SharePoint environment where I wanted to have some JavaScript libraries (like jQuery and moment.js) available across the entire site collection.  The most obvious solution would be to add a reference to each library into the master page(s) used across the sites in the site collection but for this situation editing any master page was not an option.  Instead I wanted to use User Custom Actions to do script injection.

User Custom Actions have been in SharePoint for a while, but in SharePoint 2010 they were updated to allow for “injecting” scripts into the <head> element of the DOM.  You could inject a script block (basically just a snippet of JavaScript code) or reference a .js file just like a normal <script> tag would.

I’d used User Custom Actions before to inject scripts in the context of adding buttons to the SharePoint Ribbon (another use for User Custom Actions), but every time I’d done that in the past was through the server-side object model with C# code.  For this situation I was doing development in a SharePoint Online environment, so utilizing the server-side object model was off the table.

After some trial and error I managed to come up with a completely native (by which I mean no additional libraries because obviously those libraries aren’t there when the purpose of the code is to inject them) JavaScript solution that will create a set of User Custom Actions to inject these scripts.

[code language="html"]
&lt;h1&gt;Manage Script Injection&lt;/h1&gt;
&lt;br /&gt;
&lt;div style="color: red; display: none;" id="msi-errors"&gt;&lt;/div&gt;
&lt;div id="msi-not-site-collection-admin-section" style="display: none;"&gt;
    Only site collection administrators can manage script injection.
&lt;/div&gt;
&lt;div id="msi-site-collection-admin-section" style="display: none;"&gt;
    &lt;h3&gt;Current Injected Scripts&lt;/h3&gt;
    &lt;ul id="msi-injected-scripts"&gt;
    &lt;/ul&gt;
    &lt;br /&gt;
    &lt;input type="button" value="Inject Scripts" id="msi-btn-inject" style="margin-right:10px;" /&gt;&lt;input type="button" value="Remove Scripts" id="msi-btn-uninject" /&gt;
&lt;/div&gt;
[/code]
[code language="javascript"]
(function() {
    var MyNamespace = MyNamespace || {};
    MyNamespace.Admin = MyNamespace.Admin || {};
    MyNamespace.Admin.MSI = MyNamespace.Admin.MSI || {};

    ExecuteOrDelayUntilScriptLoaded(init, 'sp.js');

    function init() {
        attachEvents();
        MyNamespace.Admin.MSI.clientContext = new SP.ClientContext.get_current();
        MyNamespace.Admin.MSI.currentUser = MyNamespace.Admin.MSI.clientContext.get_web().get_currentUser();
        MyNamespace.Admin.MSI.clientContext.load(MyNamespace.Admin.MSI.currentUser);

        MyNamespace.Admin.MSI.scriptsToInject = [
            { src: "~SiteCollection/MyAssets/components/jquery/jquery.3.0.0.min.js", sequence: 2, title: "MySite SPSite Script Injection - jQuery" },
            { src: "~SiteCollection/MyAssets/components/lodash/lodash.4.13.1.min.js", sequence: 3, title: "MySite SPSite Script Injection - lodash" },
            { src: "~SiteCollection/MyAssets/components/moment/moment.2.14.1.min.js", sequence: 4, title: "MySite SPSite Script Injection - moment" }
        ];

        MyNamespace.Admin.MSI.clientContext.executeQueryAsync(function(sender, args) {
            var isSiteAdmin = MyNamespace.Admin.MSI.currentUser.get_isSiteAdmin();
            if (isSiteAdmin) {
                fetchSiteCustomActions();
            }
            else {
                document.getElementById("msi-not-site-collection-admin-section").style.display = "block";
            }
        }, function(sender, args) {
            var msg = args.get_message() + "&lt;br /&gt;" + args.get_stackTrace();
            setError(msg);
        });
    }

    function attachEvents() {
        document.getElementById("msi-btn-inject").onclick = injectScripts;
        document.getElementById("msi-btn-uninject").onclick = uninjectScripts;
    }

    function fetchSiteCustomActions() {
        MyNamespace.Admin.MSI.currentSite = MyNamespace.Admin.MSI.clientContext.get_site();
        MyNamespace.Admin.MSI.currentSiteUserCustomActions = MyNamespace.Admin.MSI.currentSite.get_userCustomActions();
        MyNamespace.Admin.MSI.clientContext.load(MyNamespace.Admin.MSI.currentSiteUserCustomActions);
        MyNamespace.Admin.MSI.clientContext.executeQueryAsync(function(sender, args) {
            var enumerator = MyNamespace.Admin.MSI.currentSiteUserCustomActions.getEnumerator();
            var listingContainer = document.getElementById("msi-injected-scripts");
            while (enumerator.moveNext()) {
                var item = enumerator.get_current();
                if (item.get_title().indexOf("MySite SPSite Script Injection") === 0) {
                    listingContainer.innerHTML = listingContainer.innerHTML + "&lt;li&gt;" + item.get_title() + "&lt;/li&gt;";
                }
            }
            document.getElementById("msi-site-collection-admin-section").style.display = "block";
        }, function(sender, args) {
            var msg = args.get_message() + "&lt;br /&gt;" + args.get_stackTrace();
            setError(msg);
        });
    }

    function injectScripts() {
        for (var i = 0; i &lt; MyNamespace.Admin.MSI.scriptsToInject.length; i++) {
            var scriptToInject = MyNamespace.Admin.MSI.scriptsToInject[i];
            var enumerator = MyNamespace.Admin.MSI.currentSiteUserCustomActions.getEnumerator();
            var addScript = true;
            enumerator.reset();
            while (enumerator.moveNext()) {
                var item = enumerator.get_current();
                if (item.get_title() === scriptToInject.title) {
                    addScript = false;
                    break;
                }
            }
            if (addScript) {
                var newUserCustomAction = MyNamespace.Admin.MSI.currentSiteUserCustomActions.add();
                newUserCustomAction.set_location('ScriptLink');
                newUserCustomAction.set_scriptSrc(scriptToInject.src);
                newUserCustomAction.set_sequence(scriptToInject.sequence);
                newUserCustomAction.set_title(scriptToInject.title);
                newUserCustomAction.update();
            }
        }

        MyNamespace.Admin.MSI.clientContext.executeQueryAsync(function(sender, args) {
            //all done, refresh
            location.reload();
        }, function(sender, args) {
            var msg = args.get_message() + "&lt;br /&gt;" + args.get_stackTrace();
            setError(msg);
        });
    }

    function uninjectScripts() {
        var enumerator = MyNamespace.Admin.MSI.currentSiteUserCustomActions.getEnumerator();
        var scriptsToDelete = [];
        while (enumerator.moveNext()) {
            var item = enumerator.get_current();
            if (item.get_title().indexOf("MySite SPSite Script Injection") === 0) {
                scriptsToDelete.push(item);
            }
        }
        for (var i = 0; i &lt; scriptsToDelete.length; i++) {
            scriptsToDelete[i].deleteObject();
        }
        MyNamespace.Admin.MSI.clientContext.executeQueryAsync(function(sender, args) {
            //all done, refresh
            location.reload();
        }, function(sender, args) {
            var msg = args.get_message() + "&lt;br /&gt;" + args.get_stackTrace();
            setError(msg);
        });
    }

    function setError(msg) {
        var errorSection = document.getElementById("msi-errors");
        errorSection.innerHTML = msg;
        errorSection.style.display = "block";
    }
})();
[/code]

This script basically uses the client-side object model via JavaScript to access and modify the UserCustomActions collection on the site collection.  It also has safeguards against adding the same custom action more than once.  Using this I was able to create a basic script injection management solution that adds the JavaScript libraries to all pages in my entire site collection.


SharePoint 2013 Client People Picker

Interactive Business Systems is now Planet Technology. Looking for a new job? We work with some of the biggest names in tech, and we’re hiring! Check out our open jobs and make your next career move with Planet.

In SharePoint 2013, a new people picker control was introduced called the Client People Picker.  It differs from the old People Picker control we’re familiar with from previous versions of SharePoint in some key ways.

Read more

« Older Entries