Friday, November 20, 2009

SharePoint Discussion List Threading view Rating System:

I wanted to do a Rating system for the email threads we have in our SharePoint system. I have written an email thread synchronizer for SharePoint. Of course, SharePoint synchronizes the email but doesn’t thread it properly. I will write a separate blog for it.
This rating system is like this:


Figure 1:


So a user who needs to rate the email message just clicks a star and the average rating will be shown.


So how did I achieve it?


I haven’t used any c# code (except a web service). What I did was kind of changed the schema.xml file that SharePoint creates for each List. This Schema.xml file is in the appropriate folder in the 12 hive. (12\template\features\customdiscussionboard\schema.xml).


So how and where to change the Schema.xml file?

Since, I know, I need to display my star rating images before View Properties, I was curious to know where and how this is displayed. That is why, I went to Schema.xml file and fiddling it with. I saw a Status Bar field. There I saw this field. So, I changed the Schema.xml file’s StatusBar field and bingo..

This is what I added in the Schema.xml file in Status Bar field:

<!CDATA[

<HTML><![CDATA[<td style="border-style:none" nowrap="TRUE"><div>Please click star to rate: (1 low to 5 high)</div></td>]]></HTML>
<HTML><![CDATA[<td style="border-style:none" nowrap="TRUE">]]></HTML>
<HTML><![CDATA[ <div style="width:55px;"> <img alt="star_1" src="/_layouts/images/star_x_grey.gif" id="star]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[_1" ONCLICK="CurrentEventFunctions.RatingImageClicked(]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[,']]></HTML>
<Column Name="GUID" />
<HTML><![CDATA[',']]></HTML>
<Field Name="FileRef" />
<HTML><![CDATA[',this)"/><img alt="star_2" src="/_layouts/images/star_x_grey.gif" id="star]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[_2" ONCLICK="CurrentEventFunctions.RatingImageClicked(]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[,']]></HTML>
<Column Name="GUID" />
<HTML><![CDATA[',']]></HTML>
<Field Name="FileRef" />
<HTML><![CDATA[', this)" /><img alt="star_3" src="/_layouts/images/star_x_grey.gif" id="star]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[_3" ONCLICK="CurrentEventFunctions.RatingImageClicked(]]></HTML >
<Field Name="ID" />
<HTML><![CDATA[,']]></HTML>
<Column Name="GUID" />
<HTML><![CDATA[',']]></HTML>
<Field Name="FileRef" />
<HTML><![CDATA[', this)" /><img alt="star_4" src="/_layouts/images/star_x_grey.gif" id="star]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[_4" ONCLICK="CurrentEventFunctions.RatingImageClicked(]]></HTML >
<Field Name="ID" />
<HTML><![CDATA[,']]></HTML>
<Column Name="GUID" />
<HTML><![CDATA[',']]></HTML>
<Field Name="FileRef" />
<HTML><![CDATA[',this)"/><img alt="star_5" src="/_layouts/images/star_x_grey.gif" id="star]]></HTML>
<Field Name="ID" />
<HTML><![CDATA[_5" ONCLICK="CurrentEventFunctions.RatingImageClicked(']]></HTML >
<Field Name="ID" />
<HTML><![CDATA[',']]></HTML>
<Column Name="GUID" />
<HTML><![CDATA[',']]></HTML>
<Field Name="FileRef" />
<HTML><![CDATA[', this)" onload="CurrentEventFunctions.RatingLastImageLoad(']]></HTML>
<Field Name="ThreadTopic" />
<HTML><![CDATA[',']]></HTML>
<Field Name ="ID" />
<HTML><![CDATA[',this);return false;"/></div></td>]]></HTML>
]]>
 
Then, I added the javascript functions in the .master file.
 
<script language="javascript" type="text/javascript" >


function EventFunctions (loadedimage)
{
    this.loadimage=loadedimage;
}

EventFunctions.prototype.RatingLastImageLoad= function(rating,id, imgStar)
{
    if (this.loadimage) return; //this is for recursive avoiding
    if (rating.indexOf("~")>=0)
   {
      var index = rating.split("~")[1];
      if (index>=0)
     {
         for (i=1;i<=index;i++)
        {
           var imgstarmakeorange = document.getElementById("star" + id + "_" + i);
           if (imgstarmakeorange != null)
           {
               this.loadimage=true;
               imgstarmakeorange.src = "/_layouts/images/star_x_orange.gif";
               this.loadimage=false;
            }
         }
      }
  }
}
EventFunctions.prototype.RatingImageClicked =function (id, listid, parentlistid, objstar)
{
    if (typeof _spUserId != "undefined")
   {
       this.loadimage=true;
       var intStarindex = objstar.id.split("_")[1];
       this.UpdateStars(id, intStarindex);
       this.callService(id, listid, parentlistid, _spUserId,intStarindex);
       this.loadimage=false;
    }
else
   alert( "You need to signin to rate");
}

var CurrentEventFunctions = new EventFunctions(false);

EventFunctions.prototype.callService = function (id, listid, parentlistid, UserId,intStarindex )
{
var strUrl = "http://yourserver. com:<port number>/Service.asmx?WSDL";
divWbSvc.useService(strUrl,"divSvc");
var iCallID;
if (divWbSvc.divSvc)
{
iCallID = divWbSvc.divSvc.callService(this.updatePage,"InsertRatingsandReturnRatingAvg",UserId, listid,
                                                                     parentlistid,intStarindex, id, true);
}
}
EventFunctions.prototype.updatePage = function (str)
{
    if (str.error)
   {
      //alert(str.errorDetail.string);
      //handle error
    }
    else
   {
        var retVal = str.value;
        var retVals = retVal.split("~");
        //need to write logic here
     }
}
EventFunctions.prototype.UpdateStars = function (starindex, rating)
{
    this.loadimage=true;
    //get the star value (grey/orange) of the current index
    var imgstarindex = document.getElementById("star" + starindex + "_" + rating);
    var Arraysrc = imgstarindex.src.split("/");
    var intlen = Arraysrc.length;
    var imgstarindexvalue = Arraysrc[intlen-1]; 
    //first make everything grey
    for (i=1;i<=5;i++)
    {
       var imgstarmakegrey = document.getElementById("star" + starindex + "_" + i);
        if (imgstarmakegrey != null)
         imgstarmakegrey.src = "/_layouts/images/star_x_grey.gif";
     }
     //second make till the image clicked or rating -1 to orange
      for (i=1;i<=rating-1;i++)
     {
       var imgstarmakeorange = document.getElementById("star" + starindex + "_" + i);
       if (imgstarmakeorange != null)
          imgstarmakeorange.src = "/_layouts/images/star_x_orange.gif";
      }
     // now check if the image clicked is orange or grey
     var imgstarclicked = document.getElementById("star" + starindex + "_" + rating);
     if (imgstarindexvalue == "star_x_grey.gif")
         imgstarclicked.src = "/_layouts/images/star_x_orange.gif";
     else
          imgstarclicked.src = "/_layouts/images/star_x_grey.gif";
     this.loadimage=false;
}

</script>
You need to add a Grey star and Orange star image under the layouts images folder.

What I have done in my service is I insert the user, listid, folder and ratings and figure out the average rating and store it in the ThreadTopic field (actually append the ThreadTopic field with a delimiter “~”).

PS: I am attaching the images :



No comments:

Post a Comment