Serialize list items from lists.asmx

Web service list.asmx is deprecated, but somehow it seems to be the only way to obtain the desired results. For example, I am not aware of any other way to expand recurrence from an event list using client side code. So, in case you are required to use it, here is how you can obtain an array of objects from XML sent back by the web service.

function parseResponse(xmlResponse) {
    /// <summary>Obtain an array of objects from server responseXML</summary>
    /// <param name="xmlResponse"></param>
    /// <returns type="Array"></returns>


    var items = new Array();
    var rows = (typeof (xmlResponse.getElementsByTagNameNS) === 'undefined') ? xmlResponse.getElementsByTagName("z:row") : xmlResponse.getElementsByTagNameNS("*", "row");

    for (var i = 0; i < rows.length; i++) {
        var row = rows.item(i);
        var item = new Object();
        for (var j = 0; j < row.attributes.length; j++) {
            var currentNodeName = row.attributes[j].nodeName.replace('ows_', '');
            var currentNodeValue = row.attributes[j].nodeValue;
            if ((currentNodeValue == undefined) || (currentNodeValue == null)) {
                item[currentNodeName] = '';
            }
            else {
                item[currentNodeName] = currentNodeValue;
            }
        }
        items.push(item);
    }
    return items;
}

The function worked for me in Chrome, IE11 and Firefox. However, it seems “nodeValue” is a deprecated property, is still working, but it should be replaced with “value” property to avoid possible future problems.

Advertisements

Install wsp files placed in the same directory with PowerShell script

If you are required to deploy a big number of wsp files, the best way is to put them in the same folder with PowerShell script and make the script install them one by one. This way you won’t need to spend time to execute Add-SPSolution and Install-SPSolution for each one.

Add-PSSnapin Microsoft.SharePoint.Powershell;

# Input the web application name
$webApplication = Read-Host "Please enter the web application name";
# Calculate the script directory
$scriptDirectory = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition;
# Get the wsp files placed in script directory
Write-Host "Retreiving *.wsp files";
$wspFiles= Get-ChildItem $scriptDirectory *.wsp|where-object {!($_.psiscontainer)};

# Iterate through all wsp files and add and install them
foreach($wspFile in $wspFiles) {
   
   $solutionPath = $wspFile.FullName;
   $solutionName = $wspFile.name;

   # Add solution
   Write-Host "Adding solution " + $solutionName;
   Add-SPSolution $solutionPath;
   Write-Host  $solutionName + " was added to succesfully"; 
   
   # Install solution
   Write-Host "Installing solution " + $solutionName;
   Install-SPSolution -Identity $solutionName -WebApplication $webApplication -GacDeployment;
   Write-Host $solutionName + " was installed succesfully";     
    
}

Create calendar mark-up for Windows Phone

For didactic purpose I have started to create a calendar mark-up for Windows Phone using Silverlight technology. Silverlight is native for Windows Phone and this is one of the reasons I choose it. The final scope is to have something like this.

CalendarWindowsPhone

First step you need to do is to add a user control in your project. In my case I have created a folder called Controls and inside it I have added a user control called Calendar. After this step is done, is time to move to the calendar logic itself. First of all, you need a grid with 7 columns and 8 rows. 7 columns because I we have only seven days is an week and 8 rows you need for the following distribution:
– 1st row is containing buttons for navigation to previous or next month and to display selected month and year.
– 2nd row is containing days of the week.
– Rows 3,4,5,6,7 are containing dates for selected month
– Last row is for displaying additional data based on selected date. It’s all about developers imagination what data wants to display and how and I won’t talk about this.

The CAML code is simple. You can note the grid, days of the week displayed in blocks of text wrapped in borders controls and a long list selector which can be used to display additional date.

<UserControl xmlns:Controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  x:Class="PhoneCorporateApplication.Controls.Calendar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:sharecontrols="clr-namespace:PhoneCorporateApplication.Controls"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">
    
    <Grid x:Name="LayoutRoot"  Background="#000" Loaded="LayoutRoot_Loaded">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"  />
            <RowDefinition Height="Auto"  />
            <RowDefinition Height="Auto" x:Name="FirstWeek"  />
            <RowDefinition Height="Auto" x:Name="SecondWeek"  />
            <RowDefinition Height="Auto" x:Name="ThirdWeek"  />
            <RowDefinition Height="Auto" x:Name="FourthWeek"  />
            <RowDefinition Height="Auto" x:Name="FifthWeek"  />
            <RowDefinition Height="Auto" x:Name="SixthWeek"  />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>


        <Button Grid.Row="0" Grid.Column="0" Name="btnPrevMonth"  Content="&lt;" BorderThickness="0" Click="btnPrevMonth_Click" />
        <TextBlock Name="txtMonthAndYear" Text="" VerticalAlignment="Center" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="5" TextAlignment="Center"  />
        <Button Grid.Row="0" Grid.Column="6" Name="btnNextMonth"  Content="&gt;" BorderThickness="0" Click="btnNextMonth_Click" />


        <!-- Calendar days-->
        <Border Grid.Column="0" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Text="Su" Style="{StaticResource CalendarDays}" />
        </Border>
        <Border Grid.Column="1" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock  Text="Mo" Style="{StaticResource CalendarDays}" />
        </Border>
        <Border Grid.Column="2" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Text="Tu" Style="{StaticResource CalendarDays}" />
        </Border>
        <Border Grid.Column="3" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Text="We" Style="{StaticResource CalendarDays}"  />
        </Border>
        <Border Grid.Column="4" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Grid.Column="4" Grid.Row="0" Text="Th" Style="{StaticResource CalendarDays}"  />
        </Border>
        <Border Grid.Column="5" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Grid.Column="5" Grid.Row="0" Text="Fr" Style="{StaticResource CalendarDays}" />
        </Border>
        <Border Grid.Column="6" Grid.Row="1" Background="BlueViolet" CornerRadius="4" Margin="2">
            <TextBlock Grid.Column="6" Grid.Row="0" Text="Sa" Style="{StaticResource CalendarDays}" />
        </Border>
         <StackPanel Orientation="Horizontal" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="7">

            <Controls:LongListSelector Name="ViewEvents">
              
            </Controls:LongListSelector>
         
         </StackPanel>


    </Grid>
</UserControl>

From this code we missed dates for selected months, but this will be added dynamically from the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace PhoneCorporateApplication.Controls
{
    public partial class Calendar : UserControl
    {
        /// <summary>
        /// Months names
        /// </summary>
        string[] months = new string[12] { "January","February","March","April","May","June","July","August","September","October","November","December" };
        
        /// <summary>
        /// Selected month
        /// </summary>
        int selectedMonth;
        /// <summary>
        /// Selected year
        /// </summary>
        int selectedYear;


        /// <summary>
        /// Draw calendar mark-up
        /// </summary>
        /// 
        /// 
        public void DrawCalendar(int year, int month)
        {
            
            CleanCalendar();
       

            this.selectedMonth = month;
            this.selectedYear = year;

            DateTime firstDay = new DateTime(year, month, 1);
            DateTime lastDay = new DateTime(year, month, DateTime.DaysInMonth(year, month));

            int week = 2;
            while (firstDay &lt;= lastDay)
            {
                var txtCalendarDate = new TextBlock();
                txtCalendarDate.Style = Application.Current.Resources[&quot;CalendarDates&quot;] as Style;
                txtCalendarDate.Text = Convert.ToString(firstDay.Day);
               
                txtCalendarDate.Loaded += txtCalendarDate_Loaded;
                txtCalendarDate.Tap += txtCalendarDate_Tap;
               

                // Create border arround date
                Border calendarDateBorder = new Border();
                calendarDateBorder.Style = Application.Current.Resources[&quot;CalendarDateBackground&quot;] as Style;
                calendarDateBorder.Child = txtCalendarDate;

                Grid.SetRow(calendarDateBorder, week);
                Grid.SetColumn(calendarDateBorder, Convert.ToInt16(firstDay.DayOfWeek));
                this.LayoutRoot.Children.Add(calendarDateBorder);
       
              
                if (firstDay.DayOfWeek == DayOfWeek.Saturday)
                {
                    week++;
                }
                firstDay = firstDay.AddDays(1);
            }


            this.txtMonthAndYear.Text = this.months.ElementAt(month - 1) + &quot; - &quot; + year;  
        }

        void txtCalendarDate_Loaded(object sender, RoutedEventArgs e)
        {
           
        }

        void txtCalendarDate_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            TextBlock txtCalendarDate = (TextBlock)sender;
            
        }


        public Calendar()
        {
            InitializeComponent();
        }

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            DrawCalendar(System.DateTime.Today.Year, System.DateTime.Today.Month);
        }


        /// <summary>
        /// Go to next month
        /// </summary>
        /// 
        /// 
        private void btnNextMonth_Click(object sender, RoutedEventArgs e)
        {
            CleanCalendar();
 
            if(this.selectedMonth == 12) {
                this.DrawCalendar(this.selectedYear + 1, 1);
            }
            else {
                this.DrawCalendar(this.selectedYear, this.selectedMonth + 1);
            }
        
        
        }

        /// <summary>
        /// Go to previous month
        /// </summary>
        /// 
        /// 
        private void btnPrevMonth_Click(object sender, RoutedEventArgs e)
        {
            CleanCalendar();
            if(this.selectedMonth == 1)
            {
                this.DrawCalendar(this.selectedYear - 1, 12);
            }
            else
            {
                this.DrawCalendar(this.selectedYear, this.selectedMonth - 1);
            }
        }


        /// <summary>
        /// Clean existing calendar data before render new mark-up
        /// </summary>
        private void CleanCalendar()
        {
            int[] rows = new int[6] { 2, 3, 4, 5, 6, 7 };
            for(int i = 0; i  0)
            {
                LayoutRoot.Children.Remove(eList.First());
            }
        }

    }
} 

The main method is DrawCalendar which accepts two integer parameters: year and month. When the user control is loaded it is called with year and month for current date. Previous and next month buttons are calling it with different parameters by adding or decreasing month and year properties with 1 month. There is method bind to tap even for each block of text representing dates of month. Depending of requirements, implementation should be done here.

A simple way to validate parameters type in JavaScript

MicrosoftAjax.js is still my favourite framework. One of the reason is the Function.validateParameters, which allows me to validate parameters type in JavaScript. However, as it seems more and more developers are choosing other frameworks, I have decided to create my own validation, off course without pretend is so reliable like the one Microsoft did.

The code includes a namespace called “System” with two classes: “Object” and “Function”. “Object” class includes only one method to get type name for provided parameter.

var System = System || {};


System.Object = {}

System.Object.getTypeName = function(instance) {   
    

    
    var ctor = instance.constructor;
    
    // Instance is string
    if(ctor.toString().indexOf('function String()') !== -1) {
        return 'String';
    }
    
    // Instance is array
    if(ctor.toString().indexOf('function Array()') !== -1) {
        return 'Array';
    }
    
    // Instance is object
    if(ctor.toString().indexOf('function Object()') !== -1) {
        return 'Object';
    }
    
    // Instance is function
     if(ctor.toString().indexOf('function Function()') !== -1) {
        return 'Function';
    } 
    
     // Instance is number
     if(ctor.toString().indexOf('function Number()') !== -1) {
        return 'Number';
    }
    
     // Instance is date
     if(ctor.toString().indexOf('function Date()') !== -1) {
        return 'Date';
    }   
    
    return 'Variant';

}

“Function” class contains all other methods to validate parameters passed to a function.

System.Function = {};

System.Function.validateParameters = function (parameters, expectedParameters) {
    

    
     for(var i = 0; i &amp;lt; expectedParameters.length; i++) {
         
         var mayBeNull = expectedParameters[i]['mayBeNull'] || false;
         var optional = expectedParameters[i]['optional'] || false;
         var type =  expectedParameters[i]['type'] || 'Variant';
         var name = expectedParameters[i]['name'];
         var e = System.Function.validateParameterType(parameters[i],type,mayBeNull,optional);
         if(e === false) {
             return false;
         }
         
     }     
     
     return true;
     
}




System.Function.validateParameterType = function(param, type, mayBeNull, optional) {
    
    // Param is null
    if(param === null) {
       return mayBeNull === false ? false : true;
    } 
   
   // Param is undefined
    if(typeof(param) === 'undefined') {
       return optional === false ? false : true;
       
    }

   
   if(type !== 'Variant') {
        // Validate parameter type
        var paramType = System.Object.getTypeName(param);
        if(paramType !== type) {
            return false;
        }
    }
   return true;
}

Usage is similar with MicrosftAjax.js, the only difference is I provided type of the object in a string, not global object itself.

function testValidation(param1, param2, param3, param4) {
    var e = System.Function.validateParameters(arguments,
            [{type:'String', name: 'param1', optional: false },
             {type:'Number', name: 'param2', optional: false },
             {type:'Object', name: 'param3', optional: false },
             {type:'Array', name: 'param4', optional: false }]);

    if(e === true) throw 'Error message here';
}


testValidation('asdasd', 1, {}, []);

However, this might be a little bit primitive, so taking a look into Microsoft Library, validation can be done in a more elegant way.

Object._get_type = function(instance) {
    var ctor = instance.constructor;
    if (!ctor || (typeof(ctor) !== "function")) {
        return Object;
    }
    return ctor;
};

Object.get_type = function(instance) {
    return Object._get_type(instance).name;
};

And this seems to work as expected.

// Alert String
var oString = 'text';
alert(Object.get_type(oString));

// Alert Number
var oNumber = 1;
alert(Object.get_type(oNumber));

// Alert Function
var oFunction = function() {};
alert(Object.get_type(oFunction));

// Alert Date
var oDate = new Date();
alert(Object.get_type(oDate));

// Alert Array
var oArray = [];
alert(Object.get_type(oArray));

// Alert Object
var oObject = {};
alert(Object.get_type(oObject));

Displaying a list from root level in a sub site

SharePoint, being organized in a hierarchical structure, requires often from the developer to store information on central (root) level to be used in sub-sites. There is a new trend today to make use of JavaScript for this, but in the same time the old dataformawebpart is still very reliable for this. Personally, I still prefer the old way as this makes from SharePoint development a sort of puzzle solving. The demonstration is made in SharePoint Online environment, but works also in SharePoint 2007, 2010 and 2013 (on premise). As, SharePoint Designer 2013 is buggy when it comes with dataformwebpart, I will explain how to do this directly in the code.

As usual, you need to create dataformwebpart structure which contains following tags: datasources, parameterbindings and xsl.

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="8" Title="My webpart" PageType="PAGE_DISPLAYFORM"  Default="FALSE" __markuptype="vsattributemarkup" partorder="3" __WebPartId="{E1FDB6EC-29CE-448B-AD4F-066EA2FE7E2E}" id="dataFromRoot">
<DataSources>
</DataSources>
<ParameterBindings>
</ParameterBindings>
<datafields></datafields>
<XSL>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:dsp="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">
	
</xsl:stylesheet>	
</XSL>
</WebPartPages:DataFormWebPart>

Now, inside the datasource tag, you need to add a data source (SPDataSource in our case).

		<SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" UseServerDataFormat="True" selectcommand="&lt;View&gt;&lt;/View&gt;" id="MySource">
		<SelectParameters>
		<WebPartPages:DataFormParameter Name="ListName" ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Company News"/>
		<asp:Parameter Name="WebID" DefaultValue="RootWeb" />
		</SelectParameters>
		</SharePoint:SPDataSource>

You can note I am using ListName parameter instead of ListId to make my data source work in other websites if the list name remains the same. Also, WebID parameter, being set to RootWeb, makes my data source to look on root level for my list.

The last thing is to write XSLT logic to be added inside XSL->xsl:stylesheet tag. In our example, it will be a simple iteration through the items.

	<xsl:template match="/">
	<xsl:for-each select="/dsQueryResponse/Rows/Row">
	<xsl:value-of select="@Title" disable-output-escaping="yes" /><br />
	</xsl:for-each>	
	</xsl:template>

Once you tested the functionality, is safe to export the webpart. For this, I usually used SharePoint Designer, which has an option to save it to file.

IMPORTANT: open exported webpart into Visual Studio and remove ListName and ListId properties. If you miss this, dataformwebpart will failed with a message: “List does not exist”.

You can now import the webpart into the site gallery and start to use it. Below is the full code I used for this example. Happy coding!

<WebPartPages:DataFormWebPart runat="server" IsIncluded="True" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="8" Title="My webpart" PageType="PAGE_DISPLAYFORM"  Default="FALSE" __markuptype="vsattributemarkup" partorder="3" __WebPartId="{E1FDB6EC-29CE-448B-AD4F-066EA2FE7E2E}" id="dataFromRoot">
<DataSources>
		<SharePoint:SPDataSource runat="server" DataSourceMode="List" UseInternalName="true" UseServerDataFormat="True" selectcommand="&lt;View&gt;&lt;/View&gt;" id="MySource"><SelectParameters><WebPartPages:DataFormParameter Name="ListName" ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Company News"/><asp:Parameter Name="WebID" DefaultValue="RootWeb" />
		</SelectParameters>
		</SharePoint:SPDataSource>

</DataSources>
<ParameterBindings>
</ParameterBindings>
<datafields></datafields>
<XSL>
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:dsp="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">
	<xsl:template match="/">
		<xsl:for-each select="/dsQueryResponse/Rows/Row">
	<xsl:value-of select="@Title" disable-output-escaping="yes" /><br />
	</xsl:for-each>	
	</xsl:template>
</xsl:stylesheet>	
</XSL>
</WebPartPages:DataFormWebPart>

Get calendar recurrent events with CAML

SharePoint calendar has the ability to store recurrent events. User can set an event to be repeated periodically several times. It can be daily, weekly monthly. But this raises a new problem for the developer. Sometimes, for the development, we might need a recurrent events to be returned as a set of different events. Here is what you can do this in a simple manner.

Getting all events for a specified month and year

Let’s assume we are requested to get all the events for a specified month and year. Using SPServices extension is very easy. I have wrap the functionality into my code, obtaining a simple function where you just need to pass name of the calendar list, a specific date into ISO format and a callback function which accepts an array of objects as parameter.

Date.toISOFormat = function (date, ignoreTime) {
    /// <summary>Date object static method to format a date to date ISO string - YYYY-MM-DDThh:mm:ssZ</summary>
    /// <param name="date" type="Date" mayBeNull="false" optional="false"></param>
    /// <param name="ignoreTime" type="Boolean" mayBeNull="false" optional="true"></param>
    /// <returns type="String">A string representing ISO format for specied date</returns>

    // If not specified, time is ignored
    var ignoreTime = ignoreTime || {};

    function pad(number) {
        // Add leading 0 if number is less then 10 (enclosed method)
        var r = String(number);
        if (r.length === 1) r = '0' + r;
        return r;
    }

    var Y = date.getFullYear();
    var M = pad(date.getMonth() + 1);
    var D = pad(date.getDate());
    if (ignoreTime === false) return Y + '-' + M + '-' + D + 'T00:00:00Z';


    var h = pad(date.getHours());
    var m = pad(date.getMinutes());
    var s = pad(date.getSeconds());
    return Y + '-' + M + '-' + D + 'T' + h + ':' + m + ':' + s + 'Z';
}





// Create Shp namespace
var Shp = Shp || {};

Shp.ListItem = function (xmlNode) {
    /// <summary>Object representing list item, built from xml node obtained for lists.asmx web service</summary>
    /// <param name="xmlNode" type="XML" mayBeNull="false" optional="false">XML node for list item</param>
    this.listItem = new Object();
    this._parseResponse(xmlNode);
}

Shp.ListItem.prototype._parseResponse = function (xmlNode) {
    /// <summary>Internal method of ListItem to parse xml node and enclose data into listItem property</summary>
    /// <param name="xmlNode" type="XML" mayBeNull="false" optional="false">XML node for list item</param>
    for (var j = 0; j < xmlNode.attributes.length; j++) {
        var nodeName = xmlNode.attributes[j].nodeName.replace('ows_', '');
        var nodeValue = xmlNode.attributes[j].nodeValue;
        this.listItem[nodeName] = (nodeValue === undefined || nodeValue === null) ? '' : nodeValue;
    }
}

Shp.ListItem.prototype.get_item = function (field) {
    /// <summary>Internal method of ListItem to parse xml node and enclose data into listItem property</summary>
    /// <param name="field" type="String" mayBeNull="false" optional="false">XML node for list item</param>
    var fieldValue = (this.listItem.hasOwnProperty(field) === true) ? this.listItem[field] : '';
    return fieldValue;
}





// Shp.Lists object
Shp.Lists = {};


Shp.Lists._serializeResponse = function (xml) {
    /// <summary>Parse XML server response and convert it into an array of Shp.ListItem objects</summary>
    /// <param name="xml" type="XML" mayBeNull="false" optional="false">A date object. Month data where specified date is included will be returned.</param>
    /// <returns type="Array" elementsType="Shp.ListItem"></returns>

    var items = new Array();
    var rows = xml.getElementsByTagName("z:row");
    for (var i = 0; i < rows.length; i++) {
        items.push(new Shp.ListItem(rows[i]));
    }
    return items;
}

Shp.Lists.getMonthEvents = function (list, date, callback) {
    /// <summary>Get events from a specified calendar list based on a specified date.</summary>
    /// <param name="listName" type="String" mayBeNull="false" optional="false">Calendar list name</param>
    /// <param name="date" type="Date" mayBeNull="false" optional="false">A date object. Month data where specified date is included will be returned.</param>
    /// <param name="callback" type="Function" mayBeNull="false" optional="false"></param>

    // We set calendar date in the middle of the month. Seems SharePoint Online did not return correct results if I set to first day of month
    var calendarDate = new Date(date.getFullYear(), date.getMonth(), 15);
    var month = date.getMonth();
    var year = date.getFullYear();

    function isInRange(dateString) {
        /// enclosed function to check if date is in range
        var dt = dateString.split(' ')[0];
        var y = parseFloat(dt.split('-')[0]);
        var m = parseFloat(dt.split('-')[1]) - 1;
        return (y === year && m === month);
    }


    var caml = "<Query>" +
                   "<Where>" +
                       "<DateRangesOverlap>" +
                           "<FieldRef Name='EventDate' />" +
                           "<FieldRef Name='EndDate' />" +
                           "<FieldRef Name='RecurrenceID' />" +
                           "<Value Type='DateTime' IncludeTimeValue='FALSE'>" +
                               "<Month />" +
                            "</Value>" +
                        "</DateRangesOverlap>" +
                   "</Where>" +
                   "<OrderBy>" +
                       "<FieldRef Name='EventDate' />" +
                    "</OrderBy>" +
               "</Query>";



    jQuery().SPServices({
        operation: 'GetListItems',
        async: true,
        listName: list,
        CAMLQuery: caml,
        CAMLRowLimit: 100,
        CAMLQueryOptions: '<QueryOptions><DateInUtc>FALSE</DateInUtc><ViewAttributes Scope="RecursiveAll" /><CalendarDate>' + Date.toISOFormat(calendarDate) + '</CalendarDate><IncludeMandatoryColumns>TRUE</IncludeMandatoryColumns><RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion><ExpandRecurrence>TRUE</ExpandRecurrence></QueryOptions>',
        completefunc: function (data, status) {
            if (status === 'success') {
                var events = Shp.Lists._serializeResponse(data.responseXML);
                var items = [];
                for (var i = 0; i < events.length; i++) {
                    var start = events[i].get_item('EventDate');
                    var end = events[i].get_item('EndDate');

                    if (isInRange(start) === true || isInRange(end) === true) {
                        items.push(events[i]);
                    }
                }
                callback(items);
            }
            else {
                alert('Cannot complete the request');
            }
        }

    });

}

So, to get all the events you just need to call a function in a was similar with this:

jQuery(document).ready(function () {


    Shp.Lists.getMonthEvents('Company Events', new Date(), function (items) {
        for (var i = 0; i < items.length; i++) {
            alert(items[i].get_item('EventDate'));
        }
    });


});

You can notice array of object received by the callback function contains Shp.ListItem objects and event if we don’t use client object model, getting a field value is pretty much similar. Also, as DateRangesOverlap has some issues and is more a calendar view than a view containing events in a month, the code is restricting the results to get accurate data. In SharePoint Online, according to what I have discovered until now, this CAML clause is not event working like in SharePoint 2010 and I get different results if CalendarDate is the first day of the month or, for example, the 15th.

Getting all events for a specified date

This request is a little bit more easier to complete. That’s because data obtain for a date is accurate and you don’t need to adjust the results. In a similar way, you can create function to get the data from calendar list.

Shp.Lists.getDayEvents = function (list, date, callback) {
    /// <summary>Get events from a specified calendar list based on a specified date.</summary>
    /// <param name="listName" type="String" mayBeNull="false" optional="false">Calendar list name</param>
    /// <param name="date" type="Date" mayBeNull="false" optional="false">A date object.</param>
    /// <param name="callback" type="Function" mayBeNull="false" optional="false"></param>

    var caml = "<Query>" +
                   "<Where>" +
                       "<DateRangesOverlap>" +
                           "<FieldRef Name='EventDate' />" +
                           "<FieldRef Name='EndDate' />" +
                           "<FieldRef Name='RecurrenceID' />" +
                           "<Value Type='DateTime' IncludeTimeValue='FALSE'>" +
                               "<Today />" +
                            "</Value>" +
                        "</DateRangesOverlap>" +
                   "</Where>" +
                   "<OrderBy>" +
                       "<FieldRef Name='EventDate' />" +
                    "</OrderBy>" +
               "</Query>";



    jQuery().SPServices({
        operation: 'GetListItems',
        async: true,
        listName: list,
        CAMLQuery: caml,
        CAMLRowLimit: 100,
        CAMLQueryOptions: '<QueryOptions><DateInUtc>FALSE</DateInUtc><ViewAttributes Scope="RecursiveAll" /><CalendarDate>' + Date.toISOFormat(date) + '</CalendarDate><IncludeMandatoryColumns>TRUE</IncludeMandatoryColumns><RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion><ExpandRecurrence>TRUE</ExpandRecurrence></QueryOptions>',
        completefunc: function (data, status) {
            if (status === 'success') {
                var events = Shp.Lists._serializeResponse(data.responseXML);
                callback(events);
            }
            else {
                alert('Cannot complete the request');
            }
        }

    });

}

What it seems it Today from CAML string is not actually current date. It represent the date you specified as CalendarDate in QueryOptions section.

However, it seems in SharePoint Online, selecting first day of the month is producing and error and gives me also the event from the last day of previous month. For the moment I have no idea why this is happening, but my intention is to contact Microsoft to ask for more information.