Thursday 29 November 2012

Add/Remove/Check Current User Against a Specific Group

//Check if current user is in a specific group
function isCurrentUserInGroup(groupId, funUserInGroup, funUserNotInGroup, funOnError) {
    var ctx = new SP.ClientContext.get_current();
    var currentUser = ctx.get_web().get_currentUser();
    ctx.load(currentUser, 'Id', 'LoginName');
    var group = ctx.get_web().get_siteGroups().getById(groupId);
    var users = group.get_users();
    ctx.load(users);
 
    ctx.executeQueryAsync(function (sender, args) {
        //See whether the user exists
        var userFound = false;
        var userEnumerator = users.getEnumerator();
        while (userEnumerator.moveNext() && !userFound) {
            var user = userEnumerator.get_current();
            if (user.get_id() == currentUser.get_id()) {
                //User exists in the group
                userFound = true;
                if (funUserInGroup != null)
                    funUserInGroup();
            }
        }
        //User doesn't exist in the group
        if (!userFound && (funUserNotInGroup != null))
            funUserNotInGroup();
 
    }, function (sender, args) {
        if (funOnError != null)
            funOnError(sender, args);
    });
}
 
//Add current user to specific group
function addCurrentUserToGroup(groupId, funOnSuccess, funOnError) {
    var ctx = new SP.ClientContext.get_current();
    var currentUser = ctx.get_web().get_currentUser();
    ctx.load(currentUser);
    var group = ctx.get_web().get_siteGroups().getById(groupId);
    ctx.load(group);
    group.get_users().addUser(currentUser);
 
    ctx.executeQueryAsync(function (sender, args) {
        if (funOnSuccess != null)
            funOnSuccess(sender, args);
    }, function (sender, args) {
        if (funOnError != null)
            funOnError(sender, args);
    });
}
 
//Remove current user from specific group
function removeCurrentUserFromGroup(groupId, funOnSuccess, funOnError) {
    var ctx = new SP.ClientContext.get_current();
    var currentUser = ctx.get_web().get_currentUser();
    ctx.load(currentUser);
    var group = ctx.get_web().get_siteGroups().getById(groupId);
    ctx.load(group);
    group.get_users().remove(currentUser);
 
    ctx.executeQueryAsync(function (sender, args) {
        if (funOnSuccess != null)
            funOnSuccess(sender, args);
    }, function (sender, args) {
        if (funOnError != null)
            funOnError(sender, args);
    });
}
 

Wednesday 31 October 2012

How to Write a jQuery Plugin

It is actually pretty simple, you just have to follow a basic template. Here I am showing you how to build one to change elements to a round shape. Please note that because I use border radius here in the example you need IE9+ to view the result.

(function ($) {
    //This is where you define your plugin name, in this case - makeMeRound
    $.fn.makeMeRound = function (options) {

        //Extend default settings with options passed through paramete
        var settings = $.extend({
            //Below are default settings, can be overridden by parameter
            'border_color': 'red',
            'border_width': '2px'
        }, options);

        //Wrapped in a each loop in case jQuery selector returns a collection of elements
        //We return this here to maintain chainability during method calls
        return this.each(function () {
            //Below is the core of the plugin
            var max = $(this).width() > $(this).height() ? $(this).width() : $(this).height();
            $(this).css('width', max).css('height', max).css('border-color', settings.border_color).css('border-width', settings.border_width).css('border-radius', '50% 50% 50% 50%');
        });

    };

})(jQuery); //To make sure that your plugin doesn't collide with other libraries that might use the dollar sign
 
//Calling plugin
$(document).ready(function () {
    $('input').makeMeRound(); //use default setting
    $('img').makeMeRound({ 'border_width': '2px' }); //specify custom setting
});

The above script operating on the html below

<input type="button" value="Click Me" style="border-width:1px;width:100px;height:25px;"/>
<img border="1px" src="http://www.tutordoctor.com/sites/default/files/Halloween.jpg" />

will produce the following result
 
 

Thursday 25 October 2012

Using Anonymous Type as Method Parameter


Came across a petty good article with code ready for copy and paste:
http://blog.functionalfun.net/2010/08/practical-linq-6-anonymous-types-as.html

This one shows how to convert an object to Dynamic:
http://blog.jorgef.net/2011/06/converting-any-object-to-dynamic.html

How To Calculate Display Form Absolute URL



string serverUrl = item.ParentList.ParentWeb.Site.Url;

if(item.ParentList.ParentWeb.Site.ServerRelativeUrl != "/")           
    serverUrl= item.ParentList.ParentWeb.Site.Url.Substring(0, item.ParentList.ParentWeb.Site.Url.IndexOf(item.ParentList.ParentWeb.Site.ServerRelativeUrl));

string absoluteUrl = String.Format("{0}{1}?id={2}", serverUrl, item.ParentList.DefaultDisplayFormUrl, item.ID.ToString());



Friday 19 October 2012

How To Check Whether Current User Belongs To A Certain Group Using JavaScript

Using JavaScript Client Object Model:
 
function isCurrentUserInGroup(groupName, functionUserInGroup, functionUserNotInGroup, functionGroupNotFound, functionOnError) {
    var ctx = new SP.ClientContext.get_current();
    //Get info of current user
    var currentUser = ctx.get_web().get_currentUser();
    ctx.load(currentUser, 'Id', 'LoginName');
    //Retrieve all site groups
    var groups = ctx.get_web().get_siteGroups();
    ctx.load(groups);
 
    ctx.executeQueryAsync(function (sender, args) {
        //See whether the group exists
        var groupFound = false;
        var groupEnumerator = groups.getEnumerator();
        while (groupEnumerator.moveNext() && !groupFound) {
            var group = groupEnumerator.get_current();
            if (group.get_title() == groupName) {
                //Found the group, now try to load users of this group
                groupFound = true;
                var users = group.get_users();
                ctx.load(users);
                ctx.executeQueryAsync(function (sender, args) {
                    //See whether the user exists
                    var userFound = false;
                    var userEnumerator = users.getEnumerator();
                    while (userEnumerator.moveNext() && !userFound) {
                        var user = userEnumerator.get_current();
                        if (user.get_id() == currentUser.get_id()) {
                            //User exists in the group
                            userFound = true;
 
                            if (functionUserInGroup != null)
                                functionUserInGroup();
                        }
                    }
 
                    //User doesn't exist in the group
                    if (!userFound && (functionUserNotInGroup != null))
                        functionUserNotInGroup();
 
                }, function (sender, args) {
                    if (functionOnError != null)
                        functionOnError(sender, args);
 
                });
            }
        }
 
        //Group doesn't exist
        if (!groupFound && (functionGroupNotFound != null))
            functionGroupNotFound();
 
    }, function (sender, args) {
        if (functionOnError != null)
            functionOnError(sender, args);
 
    })
 
}
 
// Sample usage 
ExecuteOrDelayUntilScriptLoaded(function () {
    isCurrentUserInGroup('Approvers',
                         function () {
                            alert('User is in the group.');
                         },
                         function () {
                            alert('User is NOT in the group.');
                         },
                         function () {
                             alert('Group does NOT exist.');
                         },
                         function (sender, args) {
                             alert('Request failed.' + args.get_message() + '\n' + args.get_stackTrace());
                         });
}, "sp.js");
 

Wednesday 17 October 2012

How To Override Created/Created By/Modified/Modified By Fields

A lot of people ran into issues when trying to achieve the goal. The trick is really simple, you just need to call SPListItem.UpdateOverwriteVersion() instead of SPListItem.Update() or SPListItem.SystemUpdate().
                             
         item["Author"] = web.SiteUsers["sp2010\\user1"];
         item["Editor"] = web.SiteUsers["sp2010\\user2"];
         item["Created"] = DateTime.Now.AddYears(-50);
         item["Modified"] = DateTime.Now.AddYears(50);

         item.UpdateOverwriteVersion();




 

Tuesday 24 April 2012

Sharing A Site Collection Term Store Among Multiple Site Collections

Site collection term stores are just special groups (IsSiteCollectionGroup = true) in an MMS term store (TaxonomySession.DefaultSiteCollectionTermStore). By default there is a one to one mapping between a site collection and the associated group, but in theory a group can be accessed by multiple site collections, and a site collection can only have one such group.

For each site collection, the root web o contains a property key in the form of SiteCollectionGroupId{Guid}, i.e. SiteCollectionGroupId75e2d28e-01ce-4100-b130-7898bed9ad24, the value of this property is the id of the corresponding group in the term store which serves as the "site collection term store" for this site collection.

Each group has a property called SiteCollectionAccessIds that contains a list of site collection IDs of which has access to this group; by default it only contains a single value.

Once you understand the information above, it is not difficult to achieve sharing a group among multiple site collections. Let’s say you have site collection SiteA and SiteB and you want them to share the same site collection term store, follow the steps below:
  1. Identify the site collection group SiteA is currently using. This can be done by examine SiteA.RootWeb.AllProperties and look for the key SiteCollectionGroupId{Guid}, mark down the value.
  2. Locate the site collection group based on the id retrieved from step 1 above, and then add SiteB.ID to this group’s SiteCollectionAccessIds.
  3. Point SiteB to the group identified in step 2. This can be done by modifying SiteB.RootWeb.AllProperties["SiteCollectionGroupId{Guid}"]with the group id retrieved from step 1.
You are done!

Inspired by the link below:
Restore a link between a site collection and a local term store group after restoring site collection from backup.

Friday 30 March 2012

Binding Custom Action to Specific List Instance

In Elements.xml for custom action, use $ListId:Lists/xxx; as RgistrationId, replace xxx with the static name of your list. e.g.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction   Id="RibbonTest"
                Location="CommandUI.Ribbon"
                RegistrationId="$ListId:Lists/MyList;"
                RegistrationType="List"
                Sequence="1">
  
Please note that this approach only works in sandboxed solution, it doesn't work in a farm solution.  

Tuesday 28 February 2012

Override XSL templates in XSLT List View Web Part


You don’t even need to edit the page in SPD. XSLT List View Web Part has the ability to specify a XSL file through web part property, and the templates defined in the file will take precedence over the OOTB XSL code.  Now you can override the XSL templates selectively. Just save the custom XSL file in a library and point to it.
 In the example below I redefined the template for Description column:

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office" ddwrt:ghost="show_all"
  <xsl:include href="/_layouts/xsl/main.xsl"/> 
  <xsl:include href="/_layouts/xsl/internal.xsl"/>   
   <xsl:template name="FieldRef_Text_body.Description" ddwrt:dvt_mode="body" match ="FieldRef[@Name='Description']" mode="Text_body" ddwrt:ghost="hide">
  <xsl:param name="thisNode" select="."/>
  <xsl:value-of select="$thisNode/@Description" />
 </xsl:template>  
</xsl:stylesheet>

In order to view the raw xml returned by the query, point to another custom XSL file that contains the following content:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:template match="/">
    <xmp>
      <xsl:copy-of select="*"/>
    </xmp>
  </xsl:template>
</xsl:stylesheet>