SharePoint Dragons

Nikander & Margriet on SharePoint

Tag Archives: jQuery

Tipsy

Let’s start our day with a nice little tip about a jQuery plugin called Tipsy: http://onehackoranother.com/projects/jquery/tipsy/ , it provides Facebook-like tooltips effects and is quite nice.

Advertisements

The riddle of the five drop down lists with unique values

In a way, this post is a follow up of blog post https://sharepointdragons.com/2012/04/18/adding-jquery-to-a-visual-web-part-and-then-implement-parentchild-radio-buttons/. If you know your way around visual web parts or user controls, you don’t need to read it per se. If you don’t understand the contents of this post, it’s advisable to read it first.

Question: Suppose you have five drop down lists with an identical set of values (1-5 in this example), and suppose each selected value within this group of five lists needs to be unique. How do you implement that?

Answer: Well, a good way to that would be to use jQuery to handle the client-side validation, and implement a server-side version that kicks in if JavaScript is disabled or circumvented. The code below consists of a user control (.ascx) used in a visual web part and it’s code behind file.

Please note: The user control contains a CustomValidator control that doesn’t use the ControlToValidate property. This is because we’re not validating a specific control, instead we’re validating all list controls.This does mean that the Value property of the arguments parameter always contains an empty string.

Here’s the code for the user control (*.ascx):

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register TagPrefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true” CodeBehind=”VisualWebPart1UserControl.ascx.cs”
    Inherits=”VisualWebPartProject1.VisualWebPart1.VisualWebPart1UserControl” %>
<asp:Label ID=”Label1″ runat=”server” Text=”Label”></asp:Label>
<SharePoint:ScriptLink ID=”ScriptLink1″ runat=”server” Name=”~sitecollection/SiteAssets/MyAssets/jquery-1.7.js” />

<script type=”text/javascript”>
    // Contains a list of priority values and the amount of occurrences.
    // E.g.: value 1 is selected 0 times, value 2 is selected 3 times.
    var _arrPrios;

    // Resets all priority values to zero occurrences.
    function Init() {
        // First is dummy entry, this makes it easier to understand the mapping between array index position and drop down list values.
        _arrPrios = [0, 0, 0, 0, 0, 0];
    }
   
    // Checks if all drop down lists contain a unique value.   
    function ValidateLists(src, args) {
        Init();
       
        // Select all priority drop down lists.
        $(“#divPrioLists select :selected”).each(function () {
            AddSelectedValue($(this).val());
        });
       
        // Skip first dummy entry (index = 0).       
        for (var i = 1; i < _arrPrios.length; i++) {
            if (_arrPrios[i] != 1) {               
                args.IsValid = false;
                return false;
            }
        }       

        args.IsValid = true;
    }

    // Count occurrences for every selected value (e.g. end user selected “1” 0 times, “2” 3 times.
    function AddSelectedValue(intValue) {
        _arrPrios[intValue] = ++_arrPrios[intValue];
    }
</script>

<asp:CustomValidator id=”CustomValidator2″ runat=”server” ErrorMessage = “All priority lists must have unique values”
ClientValidationFunction=”ValidateLists” OnServerValidate=”ValidateLists” >
</asp:CustomValidator>

<div id=”divPrioLists”>

<asp:DropDownList ID=”list1″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list2″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list3″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list4″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list5″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

</div>

<asp:Button ID=”btnSubmit”  runat=”server” Text=”Submit” />

Here’s the code for the code-behind file of the user control:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace VisualWebPartProject1.VisualWebPart1
{
    public partial class VisualWebPart1UserControl : UserControl
    {

        protected override void OnInit(EventArgs e)
        {           
            // At this point, on a postback, the page hasn’t been validated yet.
            // You could call Page.Validate() explicitly or follow the normal flow of events.           
        }

        protected override void OnLoad(EventArgs e)
        {
            // At this point, on a postback, the page hasn’t been validated yet.
            // You could call Page.Validate() explicitly or follow the normal flow of events.           
        }

        protected override void OnPreRender(EventArgs e)
        {
            // The page has been validated on a postback.
            if (Page.IsPostBack && Page.IsValid)
            {

            }
        }

        // Contains a list of priority values and the amount of occurrences.
        // E.g.: value 1 is selected 0 times, value 2 is selected 3 times.
        private int[] _arrPrios = { 0, 0, 0, 0, 0, 0 };

        /// <summary>
        /// Server-side validation is equivalent to jQuery version, but kicks in in case end user disables JavaScript,
        /// or maliscuously tries to circumvent client-side validation.
        /// </summary>
        protected void ValidateLists(object source, ServerValidateEventArgs args)
        {
            // Register all selected values for all priority lists
            AddSelectedValue(list1, list2, list3, list4, list5);

            // Skip first dummy entry (index = 0).       
            for (int i = 1; i < _arrPrios.Length; i++)
            {
                if (_arrPrios[i] != 1)
                {
                    args.IsValid = false;
                    return;
                }
            }       

            args.IsValid = true;
        }

        /// <summary>
        /// Count occurrences for every selected value (e.g. end user selected “1” 0 times, “2” 3 times.
        /// </summary>       
        private void AddSelectedValue(params DropDownList[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                var currentValue = Convert.ToInt32(args[i].SelectedValue);
                _arrPrios[currentValue] = ++_arrPrios[currentValue];
            }
        }
    }
}

How to set the people picker field to the current user?

An elegant way to do it is to use a bit of server side code with jQuery:

<script type=”text/javascript”> $(document).ready(function() {

$(‘div.ms-inputuserfield’).text($().SPServices.SPGetCurrentUser({fieldName: “Title”,debug: false}));

</script>

Adding jQuery to a visual web part and then implement parent/child radio buttons

In this blog post we’ll discuss how to use jQuery in a visual web part to help implementing parent/child radio buttons. To accomplish this, we’ve borrowed ideas from other places, we’ll mention them as we go along.

First, create a new SharePoint project and add a visual web part to it. Then, download the latest version of the jQuery library. We’ll be using jquery-1.7.js.

Please note: This is the developer version, which we’ll be using throughout this example. In a production environment, you should use the minified version instead (called jquery-1.7.min.js, or the equivalent of the version you are using).

SPS 2010 contains a new type of library called Site Assets. It can be used to store resource files such as images, style sheets, and JavaScript files. We’ll use it as a new home for jquery-1.7.js. Later, we’ll discuss how to do this automatically, but the next procedure explains how to add the jQuery library manually:

  1. Open a site collection SharePoint Designer 2010 (SPD).
  2. Click the Site Assets node.
  3. Open Windows explorer and browse to jquery-1.7.js.
  4. Drag and drop it within the Site Assets node.

Since we’ve made the jQuery library available within SharePoint, we’ll be able to leverage it. We’ll do this by adding a link to it in our user control (*.ascx), like so:

<SharePoint:ScriptLink ID=”ScriptLink1″ runat=”server”

Name=”~sitecollection/SiteAssets/jquery-1.7.js” />

Please note: You shouldn’t use the ondemand=true attribute, as we want the jQuery library to be available right away.

To test if this has worked, we’re borrowing some ideas from http://blogs.msdn.com/b/yojoshi/archive/2010/06/17/using-jquery-with-sharepoint-2010.aspx :

  1. Press F5 to open MSIE (we’re assuming you’ll be able to add the visual web part to the web part page).
  2. Press F12 to bring up “Developer Tools”  (for MSIE 8 and higher).
  3. Click the Script tab and verify jQuery is getting loaded. You know this to be true if you find this entry:

    document.write(‘<script src=”/siteassets/jquery-1.7.js”></’ + ‘script>’);

  4. In the right console window, add the following jQuery command:

    $(“#MSO_ContentTable”).css(“background-color”,”cyan”);

  5. Click the Run Script button.

If the page background turns cyan, you’ll know that it works and that jQuery did it for you.

(From: http://blogs.msdn.com/b/yojoshi/archive/2010/06/17/using-jquery-with-

At this point, jQuery can be used for client-side scripting.  At this point, the code of the user control of the visual web part looks like this:
<%@ Assembly

Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities”

Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”asp” Namespace=”System.Web.UI”

Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register TagPrefix=”WebPartPages”

Namespace=”Microsoft.SharePoint.WebPartPages”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true”

CodeBehind=”VisualWebPart1UserControl.ascx.cs”
    Inherits=”VisualWebPartProject1.VisualWebPart1.VisualWebPart1UserControl” %>
<asp:Label ID=”Label1″ runat=”server” Text=”Label”></asp:Label>
<SharePoint:ScriptLink ID=”ScriptLink1″ runat=”server”

Name=”~sitecollection/SiteAssets/jquery-1.7.js” />

It only contains a reference to the jQuery library. Now, add the code to it that creates a parent/child radio button list. This idea was taken from: http://www.billsternberger.net/jquery/using-jquery-to-enable-and-disable-radio-buttons-onclick/ and it looks like this:

<script>
    $(function () {

        //init Texas
        $(‘#DivTexas :input’).attr(‘checked’, false);
        $(‘#DivTexas :input’).attr(‘disabled’, true);

        //init Virginia
        $(‘#DivVirginia :input’).attr(‘checked’, false);
        $(‘#DivVirginia :input’).attr(‘disabled’, true);
    });

    function EnableTexas() {
        //disable Virginia options
        $(‘#DivVirginia :input’).attr(‘checked’, false);
        $(‘#DivVirginia :input’).attr(‘disabled’, true);

        //enable Texas options
        $(‘#DivTexas :input’).removeAttr(‘disabled’);
    }

    function EnableVirginia() {
        //disable Texas options
        $(‘#DivTexas :input’).attr(‘checked’, false);
        $(‘#DivTexas :input’).attr(‘disabled’, true);

        //enable Virginia options
        $(‘#DivVirginia :input’).removeAttr(‘disabled’);
    }
</script>

<asp:RadioButton Value=”A” Text=”A” runat=”server” GroupName=”ParentGroup” ID=”parent1″ onclick=”EnableTexas()” />
<div id=”DivTexas”>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <asp:RadioButton Value=”AA” Text=”AA” runat=”server” GroupName=”ChildGroupA” ID=”child1″ /><br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <asp:RadioButton Value=”AB” Text=”AB” runat=”server” GroupName=”ChildGroupA” ID=”child2″ /><br />
</div>
<asp:RadioButton Value=”B” Text=”B” runat=”server” GroupName=”ParentGroup” ID=”parent2″ onclick=”EnableVirginia()” />
<div id=”DivVirginia”>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <asp:RadioButton Value=”BA” Text=”BA” runat=”server” GroupName=”ChildGroupB” ID=”child3″ /><br />
</div>

 

The result is that you can only check a child radio button if the parent radio button is checked. It looks like this:

image

Since we don’t want to add the jQuery library manually once we start deploying it, we’re taking an idea from http://www.lightningtools.com/blog/archive/2009/12/06/add-javascript-files-once-to-a-page—sharepoint-sandbox.aspx We’ll add the jQuery library as a module to our SharePoint project, and deploy it to a subfolder in the Site Assets library.

  1. Right-click SharePoint project and choose Add > New Item.
  2. Choose Module and call it MyAssets.
  3. Within the MyAssets folder, delete Sample.txt.
  4. Right-click the MyAssets folder and choose Add.
  5. Locate jquery-1.7.js (or better yet: locate the minified version) and add jquery-1.7.js.
  6. Open up Elements.xml, and add the following attribute: Url=”SiteAssets” to the Module element.

Now, the Module XML should look like this:

<?xml version=”1.0″ encoding=”utf-8″?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”>
  <Module Name=”MyAssets” Url=”SiteAssets”>
  <File Path=”MyAssets\jquery-1.7.js” Url=”MyAssets/jquery-1.7.js” />
</Module>
</Elements>

Pressing F5 causes jquery-1.7.js to be deployed to the Site Assets library, in the My Assets folder. This means you should update the link in the user control like so:

<SharePoint:ScriptLink ID=”ScriptLink1″ runat=”server”

Name=”~sitecollection/SiteAssets/MyAssets/jquery-1.7.js” />

And there you have it!

Building a jQuery Autocomplete textbox using the SharePoint REST API

So the first problem we had was to come up with a title that about sums up all the technologies and tools we’ll be using in this blog post, mainly being jQuery, jQuery UI, the SharePoint REST API and Fiddler, and make it sound spiffy as well. After abandoning that idea, we just used this title instead.

In this blog post we’re creating an autocomplete textbox that provides hints stored in a SharePoint list. The SharePoint RESTful interface is an ideal candidate to aid in this quest because jQuery makes it really easy to issue REST requests and also handles the JSON responses that the SharePoint REST API can provide really well. If you need to read up on REST we can totally recommend http://www.loisandclark.eu/Pages/rest.aspx, an article written by two very talented authors.

Because the jQuery Autocomplete widget works well with JavaScript objects containing a label and value property (or in fact, the name of the first property, label, doesn’t seem to matter, but the casing of the value property is important) we’ve decided to create a custom SharePoint list containing a Title, label and value column. We’ve called our list MyList. If you do the same you’ll be able to follow the rest of the example. Also, make sure to fill the list with some test data such as: aaa, aarde, and aardvarken.

The Autocomplete widget will show information while the user types, so we need a way to filter a specific column based on a search term. REST makes this pretty easy, although you have to be really careful when it comes to casing. For instance, if we want a list of all list items that have a value that starts with a in the Value column, all we need to do is issue the following REST request:

http://moon/_vti_bin/listdata.svc/MyList?$filter=startswith(Value,’a’)

By default, the response is XML. For our purposes, we’re more interested in JSON. If you want to work with REST and JSON it’s absolutely essential to install a tool on your dev environment that’s able to capture HTTP traffic. Here, we’ll use Fiddler (http://www.fiddler2.com/fiddler2/).

Once you start it up, it starts capturing HTTP traffic immediately (toggle between stopping and starting capturing traffic by pressing F12). Now do the following:

  • Issue the REST request: http://moon/_vti_bin/listdata.svc/MyList?$filter=startswith(Value,’a’) . Of course, you may have to change names. If you didn’t think of that yourself, don’t worry, you’ll never be able to complete the entire blog post Winking smile!
  • Press F12.
  • Locate the request in Fiddler. Right-click it and choose Unlock for Editing.
  • Press the Headers tab.
  • Find the Client section and notice that it says: Accept: */*.
  • Right-click the Accept line and choose Edit Header…. Change the value to application/json. This forces the response to be in JSON format.
  • image

  • Press F12 again so that Fiddler starts capturing web traffic again.
  • Right-click the modified request > Replay > Reissue Requests.
  • Locate the new request and inspect the body of the response by clicking JSON:
    image

This will teach you important stuff about the structure of the JSON response, which comes in handy once you need to process the information (and if you want to understand the jQuery code that’s coming up). If you remember that the autocomplete widget expects a collection of objects containing label and value properties, the following code should be understandable:

<html>
<head>
<script type=”text/javascript” src=”jquery-1.7.js”></script>
<script type=”text/javascript” src=”jquery-ui-1.8.custom.min.js”></script>
<script>
$(document).ready(function () {
  $(“input#autobox”).autocomplete({
  source: function (request, response) {
  var term = request.term;
  var restUrl = “http://moon/_vti_bin/listdata.svc/MyList?$filter=startswith(Value, ‘” + term + “‘)”;

  $.getJSON(restUrl, function (data) {
  var items = [];
  $.each(data.d.results, function (key, val) {                         
    var item = {
      label: val.Label,
      value: val.Value
      };

      items.push(item);
      });

      response(items);
      });

    }
  });
});

</script>

</head>
<body>

jQuery test page

<input type=”text” id=”autobox” />
 
</body>
</html>

This clearly demonstrates the power of jQuery as it accomplishes quite a lot in so little code. The end result is pretty:

image image image