4

The business need is to create a 'channel' page that will display thumbs of videos like a gallery, and I need to enable people to 'like' that content from the gallery page. (Standard disclaimer: I'm not all that sharp with the JavaScript, and certainly not with the SharePoint CSOM and don't claim to be.) I could use help in two areas - 1) I need to turn this into a repeatable function I can call on a series of items on the page, rather than hard-coding in a list ID and item ID. 2) Any advice on improving the code, making it more efficient (it's quite slow) or pointers to resources to do the same is greatly appreciated. This will live on a publishing site, on prem, SharePoint 2013.

//Build absolute path to the layouts root with the spHostUrl
var layoutsRoot = '/_layouts/15/';
$(function() { 
    $.getScript(layoutsRoot + "MicrosoftAjax.js", function () {
        $.getScript(layoutsRoot + "SP.core.js", function () {
            $.getScript(layoutsRoot + "SP.Runtime.js", function () {
                $.getScript(layoutsRoot + "SP.js", function () {
                    $.getScript(layoutsRoot + "SP.Publishing.js", function () {
                        $.getScript(layoutsRoot + "Reputation.js", GetLikeCount)
                    });
                });
            });
        });
     });
});
var siteUrl = '/';
var context;
var list;
var sList = '2E754CC9-F12C-4300-92D3-AC4F3869F156';
var sItem = 7;
var thisItem;
var likeDisplay;

function LikePage() {  //called when user clicks 'Like' or 'Unlike'
    var like = false;
    var likeButtonText = $("a.LikeButton").text();
    if (likeButtonText != "") {
        //Like button text not empty
        if (likeButtonText == "Like"){
            // Item is not Liked by current user
            like = true;
        }
    }
    EnsureScriptFunc('reputation.js', 'Microsoft.Office.Server.ReputationModel.Reputation', function () {
            Microsoft.Office.Server.ReputationModel.Reputation.setLike(context,sList,sItem, like);
                context.executeQueryAsync(function () {
                    GetLikeCount();
                }, function (sender, args) {
                    alert('Failed to like this. Error:' + args.get_message());
                });
            });
        }

function GetLikeCount(){ //Check to see if liked, get liked count, and if current user likes the item
    context = new SP.ClientContext(siteUrl);
    list = context.get_web().get_lists().getById(sList);
    thisItem = list.getItemById(sItem);

    context.load(thisItem, "Title","LikedBy", "ID", "LikesCount");
    context.executeQueryAsync(Function.createDelegate(this,onSuccess),Function.createDelegate(this,onFailure));
}

function onFailure(sender, args) {
    alert('Failed to get lists items. Error:' + args.get_message());
}

function onSuccess(sender, args) {
    var $v_0 = thisItem.get_item('LikedBy');
    var itemc = thisItem.get_item('LikesCount');
    if (!($v_0)) {
        //not liked by anyone
        likeDisplay = true;
        }
    if ($v_0) {
        for (var $v_1 = 0, $v_2 = $v_0.length; $v_1 < $v_2; $v_1++) {
            var $v_3 = $v_0[$v_1];
            if ($v_3.$1E_1 === _spPageContextInfo.userId) {
                //Liked by me
                likeDisplay = false;
            } else {
                //not liked by me
                likeDisplay = true;
            } 
        }             
    }
    ChangeLikeText(likeDisplay, itemc);
}

function ChangeLikeText(like, count) {  //Manage the DOM elements and presentation
    if (like) {
        $("a.LikeButton").text('Like');
    }
    else {
        $("a.LikeButton").text('Unlike');
    }
    var htmlstring = "<img alt='' src='/_layouts/15/images/LikeFull.11x11x32.png' />" + " " + String(count) + " ";
    if (count > 0)
        $(".likecount").html(htmlstring)
    else
        $(".likecount").html("");
}

Thank you for any help; it is greatly appreciated :)

  • Hi @Kevin, where I can find this code already refactored ? :) – Tito Nov 25 '15 at 14:36
7

Some recommendations:

1) Avoid using global variables. Consider to pass parameters as function arguments, for example:

function setLike(listId,itemId,like,success,error)
{
    var ctx = SP.ClientContext.get_current();
    Microsoft.Office.Server.ReputationModel.Reputation.setLike(ctx,listId,itemId, like);
    ctx.executeQueryAsync(
        function () {
            success();
        }, 
        error);
}

function getRating(listId,itemId,like,success,error)
{ 
    var ctx = SP.ClientContext.get_current();
    var list = ctx.get_web().get_lists().getById(listId);
    var item = list.getItemById(itemId);

    ctx.load(item, "Title","LikedBy", "ID", "LikesCount");
    ctx.executeQueryAsync(
        function(){
           success(item);
        },
        error);
}

Usage:

setLike(listId,itemId,true,
     function(){
        console.log('You liked this page');
        getRating(listId,itemId,
            function(item){
                var likesCount = item.get_item('LikesCount');
                console.log(String.format('This page was liked {0} times',likesCount));
            },
            logError);
     },
     logError);  

2)Regarding List Id and Item Id parameters. Since SharePoint generates PageContextInfo structure on the page, you could retrieve current List Id from pageListId property, for example:

var listId = _spPageContextInfo.pageListId;

and current List Item id from pageItemId property (on list form pages):

var itemId = _spPageContextInfo.pageItemId;

3) Instead of declaring layouts url:

var layoutsRoot = '/_layouts/15/'; 

you could utilize SP.Utilities.Utility.getLayoutsPageUrl(pageName) Method for that purpose, for example:

var spUrl = SP.Utilities.Utility.getLayoutsPageUrl('sp.js');

4) Instead of loading JS files using $.getScript method you could utilize SP.SOD.loadMultiple method to load multiple JS libraries (part of SharePoint JS library), for example:

SP.SOD.registerSod('SP.ClientContext', SP.Utilities.Utility.getLayoutsPageUrl('sp.js'));
SP.SOD.registerSod('Microsoft.Office.Server.ReputationModel.Reputation', SP.Utilities.Utility.getLayoutsPageUrl('reputation.js'));
SP.SOD.loadMultiple(['SP.ClientContext', 'Microsoft.Office.Server.ReputationModel.Reputation'], function(){

     console.log('SharePoint JS libraries have been loaded..')

});    
  • 1
    Vadim - Thanks for the response, lots of helpful advice here. One question re:#2? - I'm trying to 'like' items from a separate library, not the page itself. I'll have a group of thumbnails of videos or photos that come in as a query of a separate library - That's why I want to pass the list ID directly of the list I need, and then each item ID. Don't I? Not sure how the page context helps me to like items not in this pages library... – Kevin Lowe Mar 9 '15 at 14:02
  • Kevin, got your point regarding #2. You're right, page context could not be applied here.. – Vadim Gremyachev Mar 9 '15 at 15:18
0

Thanks for your article is very useful and its working on my page, but i need your help, i am calling rest api function to read the first 3 items of the list and i am trying to integrate the like functions code in my main code and to do that i have insert this: < div id='idnumb' >"+itemid+"< / div > in the ajax code to read id's value of each item and i am trying to set the id value to the variable as var sItem = $("div.idnumb").text(); but i have a main problem that i need to set the sItem value after the load of the list contents ( title, id , description content) ??? i tried many workaround steps but still cannot read the id of each item.

First question, this is a good solution to convert the like function code to read dynamic item value, by using $("div.idnumb").text()

and if not, please suggestion another solutions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.