At Work 02 : Add Follow/Unfollow button in ListView webparts for Document Libraries (using JSLink)

CaptureLV

This post is just another example about JSLink you can find on web. This post is about show follow/Unfollow Document link in List-view. The solution is simple. Add a text column on the List (Say FollowLink) and hide this column in forms. Include the column in Listview. Link the following JSLink code in Listview webpart.

var SPOFieldCustomizations = window.SPOFieldCustomizations || {};
SPOFieldCustomizations.CustomizeFollowLinkFieldRendering = function () {
    var fieldJsLinkOverride = {};
    fieldJsLinkOverride.Templates = {};
    fieldJsLinkOverride.OnPostRender = postRenderHandler;

    fieldJsLinkOverride.Templates.Fields = {
        // Make sure the Priority field view gets hooked up to the GetPriorityFieldIcon method defined below
        // we have to update the column name here
        'FollowLink': {
            'View': SPOFieldCustomizations.GetFollowLinkFieldMarkup
        }
    };

    // Register the rendering template
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(fieldJsLinkOverride);
};

SPOFieldCustomizations.GetFollowLinkFieldMarkup = function (ctx) {
    var followLinkMarkup = "";
    if (ctx.CurrentItem.FSObjType === "0") {
        followLinkMarkup = '<a class="ms-profile-followLink ms-heroCommandLink" href="javascript:;">' + '<span class="ms-profile-followHeroImageParent">' + '<img data-toggle="tooltip" data-placement="right" title="" id="Img' + ctx.CurrentItem.ID + '" src="/_layouts/15/images/gears_anv4.gif?rev=35" class="ms-profile-followHeroImage" ></img>' + '</span>' + '</a>';
        SPOFieldCustomizations.isFollowed('/' + ctx.CurrentItem.FileRef, 'Img' + ctx.CurrentItem.ID);
    }
    return followLinkMarkup;
};

SPOFieldCustomizations.isFollowed = function (documentUrl, imgid) {
    window.Utilities.Social.REST.LoadIsFollowed(documentUrl, _spPageContextInfo.webAbsoluteUrl, 1, function (responseData) {
        jsonObject = JSON.parse(responseData.body);
        if (jsonObject.d.IsFollowed === true) {

            $('#' + imgid).attr("title", "Click to Unfollow").attr('data-followed', '1')
            .attr('src', '/_layouts/15/images/socialcommon.png?rev=33')
            .addClass("unFollow")
        } else {
            $('#' + imgid).attr("title", "Click to Follow").attr('data-followed', '0')
            .attr('src', '/_layouts/15/images/socialcommon.png?rev=33')
            .removeClass("unFollow");
        }
        $('#' + imgid).click(function () {
            var FollowStatus = $(this).attr('data-followed');
            var url = '';
            if (FollowStatus === '1')
                url = _spPageContextInfo.webAbsoluteUrl + '/_api/social.following/stopfollowing';
            else if (FollowStatus === '0')
                url = _spPageContextInfo.webAbsoluteUrl + '/_api/social.following/follow';

            if (url !== '') {
                SPOFieldCustomizations.toggleFollow(url, documentUrl, imgid, FollowStatus);
            }
        });
    }, function (s, a, errMsg) {
        $('#' + imgid).text(errMsg);
    });

};
SPOFieldCustomizations.toggleFollow = function (url, documentUrl, imgid, FollowStatus) {
    window.Utilities.Social.REST.ToggleFollow(url, documentUrl, _spPageContextInfo.webAbsoluteUrl, 1, function (responseData) {
        var jsonObject = JSON.parse(responseData.body);
        var isfollowed = jsonObject.d.Follow;
        var stoppedFollowing = jsonObject.d.StopFollowing;

        if (isfollowed !== undefined) {
            $('#' + imgid).attr('title', 'Click to Unfollow').attr('data-followed', '1')
                          .addClass("unFollow");
        } else {
           $('#' + imgid).attr('title', 'Click to Follow').attr('data-followed', '0')
                         .removeClass("unFollow");
        }
    }, function (s, a, errMsg) {
        $('#' + imgid).text(errMsg);
    });

}

function postRenderHandler(ctx) {
    // code to execute after view render
}

// Call the function.
SPOFieldCustomizations.CustomizeFollowLinkFieldRendering();

There are few utility function calls inside this JSLink code to follow/unfollow documents. The code looks like

function LoadAndExecuteSodFunction(scriptKey, fn) {
    if (!ExecuteOrDelayUntilScriptLoaded(fn, scriptKey)) {
        LoadSodByKey(NormalizeSodKey(scriptKey));
    }
}

RegisterSod('/_layouts/15/sp.requestexecutor.js');

window.Utilities = window.Utilities || {};
window.Utilities.Social = window.Utilities.Social || {};
window.Utilities.Social.REST = window.Utilities.Social.REST || function () {
    var LoadIsFollowed = function (documentOrSiteUrl, siteurl, actortype, successcallback, failcallback) {
        var requestinfo = {
            url: siteurl + '/_api/social.following/isfollowed',
            method: "POST",
            body: JSON.stringify({
                "actor": {
                    "__metadata": {
                        "type": "SP.Social.SocialActorInfo"
                    },
                    "ActorType": actortype,
                    "ContentUri": documentOrSiteUrl,
                    "Id": null
                }
            }),
            headers: {
                "accept": "application/json;odata=verbose",
                "content-type": "application/json;odata=verbose"
            },
            success: function (responseData) {
                successcallback(responseData);
            },
            error: function (s, a, errMsg) {
                failcallback(s, a, errMsg);
            }
        };

        LoadAndExecuteSodFunction('sp.requestexecutor.js', function () {
            var executor = new SP.RequestExecutor(siteurl);
            executor.executeAsync(requestinfo);
        });
    };

    var ToggleFollow = function (url, documentOrSiteUrl, siteurl, actortype, successcallback, failcallback) {
        var requestinfo = {
            url: url,
            method: "POST",
            body: JSON.stringify({
                "actor": {
                    "__metadata": {
                        "type": "SP.Social.SocialActorInfo"
                    },
                    "ActorType": actortype,
                    "ContentUri": documentOrSiteUrl,
                    "Id": null
                }
            }),
            headers: {
                "accept": "application/json;odata=verbose",
                "content-type": "application/json;odata=verbose"
            },
            success: function (responseData) {
                successcallback(responseData);
            },
            error: function (s, a, errMsg) {
                failcallback(s, a, errMsg);
            }
        };
        LoadAndExecuteSodFunction('sp.requestexecutor.js', function () {
            var executor = new SP.RequestExecutor(siteurl);
            executor.executeAsync(requestinfo);
        });
    };
    return { LoadIsFollowed: LoadIsFollowed, ToggleFollow: ToggleFollow};
}();
Advertisement