Sunday, January 22, 2012

POST complex data to pagemethod or webservice using jQuery

In many occasion we need to post some complex data like class (object), array, list of objects to pagemethod, webmethod or web service. I have answered many such posts in asp.net forum. So, decided to list few posts here-

http://forums.asp.net/p/1688559/4454363.aspx/1?Re+Post+array+of+array+of+html+form. This post is used to post generic list of a class objects where the UI is represented as UL, LI. Each LI has a checkbox, a hidden filed and an input box. The underlying structure of the class is as-
public class ComplexData {
    public int id { get; set; }
    public bool flag { get; set; }
    public string note { get; set; }
}
http://forums.asp.net/p/1709268/4549152.aspx/1?Re+how+to+save+data+using+jquery+ajex. This post is used to post name id based class where the UI is represented as HTML table. The class structure is as-
public class NameIDData
{
    public int id { get; set; }
    public string name { get; set; }
}
http://forums.asp.net/p/1690207/4462756.aspx/1?Re+Problem+with+charset+ajax+request. This post is used to post a class which contains non English characters. The class structure is as-
public class PersonClass
{
    public Guid Userid { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Username { get; set; }
}
And input sample data is as-
            var jsonString = { "Userid": "eec756aa-56e0-4515-b3bb-70b6c31b3d8a",
                "Firstname": "сркшы",
                "Lastname": "сркшы",
                "Username": "russiantest"
            };
http://forums.asp.net/p/1694914/4482943.aspx/1?Re+Getting+form+Values+. This post is used to post some complex data with parent child relationship. The UI is little complex with field set as each row of data. And the content can be added dynamically. The class is represented as-
public class ParentChild
{
    public string Parent { get; set; }
    public string Child { get; set; }
}
http://forums.asp.net/p/1662319/4338617.aspx. This post is used to post a list of object from reading Grid View rows. The class structure goes like-
public class Screening
{
    public string ScreeningPropertyID { get; set; }
    public string ScreeningValue { get; set; }
}
http://forums.asp.net/p/1653108/4303194.aspx#4303194. This post deals with posting a string array to webmethod.

http://forums.asp.net/p/1650626/4292348.aspx#4292348. This post deals with reordering of HTML element and post the reordered list to the webmethod. The class structure goes like below-
public class DivsDetail {
    public int DivID { get; set; }
    public int Order { get; set; }
}

Friday, January 20, 2012

Validation summary popup UI modification

In this post we will discuss how to modify the UI of validation summary with some CSS and jQuery.

Problem
Suppose we have two fields named first name and last name. And we need to implement required field validation. If we use asp.net RequiredFieldValidator and ValidationSummary with ShowMessageBox="true", then we can get the following result if we are not providing any value for the text fields-

Now we know that we cannot modify the message box UI. But if we want to do so-

Solution
If we change the ValidationSummary a little by ShowMessageBox="false" ShowSummary="true" DisplayMode="BulletList", then we get the following UI-

If we check the UI created for the summary we can find the following HTML generated-
    <div style="color: red" id="vsInfo" headertext="Following error occurs:" displaymode="BulletList">
        Following error occurs:
        <ul>
            <li>Provide first name</li>
            <li>Provide last name</li></ul>
    </div>
What we can do is add a little trick here. We can use jQuery dialog to change the UI (I believe that we know how to use jQuery dialog. For reference check here).

The modified code goes here-
    <div id="dialog" style="display:none">
    </div>
    <div class="itemContent">
        <label></label>
        <div class="controls" style="display:none">
           <asp:ValidationSummary ID="vsInfo" runat="server" HeaderText="Following error occurs:"
                ShowMessageBox="false" ShowSummary="true" DisplayMode="BulletList"  />
        </div> 
    </div>   
    <script type="text/javascript">
        $(document).ready(function() {
            $("#btnSaveInfo").click(function() {
                document.TimeID = setTimeout("checkMessage()", 5);
            });
        });
        function checkMessage() {
            if ($("div#vsInfo").length > 0) {
                $("#dialog").empty();
                $("#dialog").append($("div#vsInfo UL"));
                $("#dialog").dialog({
                    title: $("div#vsInfo").text(), 
                    close: function(event, ui) {
                        clearTimeout(document.TimeID);
                    }
                });
                clearTimeout(document.TimeID);
            }
            else 
                document.TimeID = setTimeout("checkMessage()", 5);
            
        }
    </script>
What we are doing here is binding the click event to the save button, in the button click we are calling a function named checkMessage() periodically after every 5 milliseconds and checking whether a div with id vsInfo exists in the DOM. If exists, then copying the HTML of the ValidationSummary and putting it in the dialog div, opening the dialog and finally clearing the timer. So, final UI looks like-
That’s what we wanted. We can change the UI of the dialog as we need.

Download the code from here.

Wednesday, January 18, 2012

ppGallery - Lightbox Gallery with asp.net repeater

In this post, we will go through implementation of ppgallery image slider plug-in with asp.net repeater control. The plug-in information can be found here for download.

To start with this lets first see how ppgallery works. The basic implementation of goes as follows-
To use the plugin we need to take following file references-
<link href="http://www.ppplugins.com/demo/ppgallery/ppgallery/css/ppgallery.css" rel="stylesheet" type="text/css" />
<link href="http://www.ppplugins.com/demo/ppgallery/ppgallery/css/dark-hive/jquery-ui-1.8.6.custom.css" rel="stylesheet" type="text/css" />

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script> 
<script type="text/javascript" src="http://www.ppplugins.com/demo/ppgallery/ppgallery/js/ppgallery.js"></script> 
We can download the CSS and JS file to your local system and take the reference from locally.
The HTML structure of the plug-in should be like this-
<ul id="gallery">
  <li><a href="big image URL" title="Title"><img src="Thumbnail URL"></a></li>
  <li><a href="big image URL" title="Title"><img src="Thumbnail URL"></a></li>
.
.
.
.
</ul>
For example-
<ul id="gallery">
  <li><a href="http://ppplugins.com/demo/ppgallery/images/l_01.jpg" title="Example of a title goes here."><img src="http://ppplugins.com/demo/ppgallery/images/s_01.jpg"></a></li>
  <li><a href="http://ppplugins.com/demo/ppgallery/images/l_02.jpg" title="Example of a title goes here."><img src="http://ppplugins.com/demo/ppgallery/images/s_02.jpg"></a></li>
  <li><a href="http://ppplugins.com/demo/ppgallery/images/l_03.jpg" title="Example of a title goes here."><img src="http://ppplugins.com/demo/ppgallery/images/s_03.jpg"></a></li>
  <li><a href="http://ppplugins.com/demo/ppgallery/images/l_28.jpg" title="Thanks for visiting PP Plugins"><img src="http://ppplugins.com/demo/ppgallery/images/s_28.jpg"></a></li>
</ul>
And we can implement the plug-in by calling the following script-
<script type="text/javascript">
$(document).ready(function() {
 $('#gallery').ppGallery();
});
</script>
Now we can integrate the image HTML in a repeater. And the code goes below-
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link href="http://www.ppplugins.com/demo/ppgallery/ppgallery/css/ppgallery.css" rel="stylesheet" type="text/css" />
<link href="http://www.ppplugins.com/demo/ppgallery/ppgallery/css/dark-hive/jquery-ui-1.8.6.custom.css" rel="stylesheet" type="text/css" />

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script> 
<script type="text/javascript" src="http://www.ppplugins.com/demo/ppgallery/ppgallery/js/ppgallery.js"></script> 
<script type="text/javascript">
$(document).ready(function() {
        $('#gallery').ppGallery();
});
</script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Repeater ID="Repeater1" runat="server">
        <HeaderTemplate>
            <ul id="gallery">
        </HeaderTemplate>
        <ItemTemplate>
            <li><a href='<%#Eval("URL") %>' title='<%#Eval("Title") %>'>
                <img src='<%#Eval("Thumb") %>'></a></li>
        </ItemTemplate>
        <FooterTemplate>
            </ul>
        </FooterTemplate>
    </asp:Repeater>
    </form>
</body>
</html>
    protected void Page_Load(object sender, EventArgs e)
    {
        var imageDataSource = (new[] { new { URL = "http://ppplugins.com/demo/ppgallery/images/l_01.jpg", 
                                    Thumb = "http://ppplugins.com/demo/ppgallery/images/s_01.jpg" Title= "Title 1"} }).ToList();
        imageDataSource.Add(new {URL = "http://ppplugins.com/demo/ppgallery/images/l_02.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_02.jpg" Title= "Title 2"});
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_03.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_03.jpg" Title= "Title 3" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_04.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_04.jpg" Title= "Title 4" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_05.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_05.jpg" Title= "Title 5" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_06.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_06.jpg" Title= "Title 6" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_19.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_19.jpg" Title= "Title 7" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_20.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_20.jpg" Title= "Title 8" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_21.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_21.jpg" Title= "Title 9" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_22.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_22.jpg" Title= "Title 10" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_23.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_23.jpg" Title= "Title 11" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_24.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_24.jpg" Title= "Title 12" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_25.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_25.jpg" Title= "Title 13" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_26.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_26.jpg" Title= "Title 14" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_27.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_27.jpg" Title= "Title 15" });
        imageDataSource.Add(new { URL = "http://ppplugins.com/demo/ppgallery/images/l_28.jpg", Thumb = "http://ppplugins.com/demo/ppgallery/images/s_28.jpg" Title= "Title 16" });
        Repeater1.DataSource = imageDataSource;
        Repeater1.DataBind(); 
    }
This is an in memory data source. We can replace the data source as we want.

Monday, January 16, 2012

Implement drag drop events from outside in Full Calender for an ajax based data source

Introduction
With this post I will try to describe Full Calender plugin with drag and drop feature where we can drag and drop events from an Ajax based event data source outside the calender. For this to implement we need to know basics about jQuery and full calender plugin. We can get the plugin detail form this URL.

Details goes here-
CSS used in this post goes here-
   <style type='text/css'>
        body
        {
            margin-top: 40px;
            text-align: center;
            font-size: 14px;
            font-family: "Lucida Grande" ,Helvetica,Arial,Verdana,sans-serif;
        }
        #wrap
        {
            width: 1100px;
            margin: 0 auto;
        }
        #external-events
        {
            float: left;
            width: 150px;
            padding: 0 10px;
            border: 1px solid #ccc;
            background: #eee;
            text-align: left;
        }
        #external-events h4
        {
            font-size: 16px;
            margin-top: 0;
            padding-top: 1em;
        }
        .external-event
        {
            margin: 10px 0;
            padding: 2px 4px;
            background: #3366CC;
            color: #fff;
            font-size: .85em;
            cursor: pointer;
        }
        #external-events p
        {
            margin: 1.5em 0;
            font-size: 11px;
            color: #666;
        }
        #external-events p input
        {
            margin: 0;
            vertical-align: middle;
        }
        #calendar
        {
            float: right;
            width: 900px;
        }
    </style>
For this to work we need to take some CSS and JS files as a reference as follows-
    <link rel='stylesheet' type='text/css' href='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.css' />
    <link rel='stylesheet' type='text/css' href='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.print.css'
        media='print' />

    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js'></script>

    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js'></script>

    <script type='text/javascript' src='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.min.js'></script>
We can implement a full calender in a div like container as follows-
    <div id='calendar'>
    </div>
            $('#calendar').fullCalendar({
                header: {
                    left: 'prev,next today',
                    center: 'title',
                    right: 'month,agendaWeek,agendaDay'
                },
                editable: true,
                droppable: true,
                drop: function(date, allDay) {
                //drop functionality goes here
                }
            });
Now the basic construct for the problem is done. Lets add a div in the page as a container and list all the events on the div using Ajax. We will now implement drag and drop such that we can drag an event form the list of events and add the events to calender by dropping it into the full calender. To list the events in a div using Ajax we can use page method like below-
    <div id='external-events'>
        <h4>
            Draggable Events</h4>
        
        <p id="events">
            <input type='checkbox' id='drop-remove' />
            <label for='drop-remove'>
                remove after drop</label>
        </p>
    </div> 
            $.ajax({
                url: "Fill draggable events area of FullCalendar.aspx/GetEvents",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                success: function(data) {
                    $(data.d).each(function(i, item) {
                        $("#events").before($("<div class='external-event'></div>").html(item.EventName));
                    });
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    debugger;
                    alert(textStatus);
                }
            });
    [System.Web.Services.WebMethod]
    public static object GetEvents()
    {
        var obj = new { EventName = "My Event 1"};
        var objList = (new[] { obj }).ToList();
        objList.Add(new { EventName = "My Event 2" });
        objList.Add(new { EventName = "My Event 3" });
        objList.Add(new { EventName = "My Event 4" });
        objList.Add(new { EventName = "My Event 5" });
        objList.Add(new { EventName = "My Event 6" });
        objList.Add(new { EventName = "My Event 7" });
        return objList;
    }
In the above code we have some in memory object as event datasource. We can change to any data source as we need.
Now we need to make the event divs, constructed in the above js code, as draggable. We can do this by implementing the draggable UI plugin by modifying the success method of the Ajax call like below-
                success: function(data) {
                    $(data.d).each(function(i, item) {
                        $("#events").before($("<div class='external-event'></div>").html(item.EventName));
                    });
                    $('#external-events div.external-event').each(function() {
                        var eventObject = {
                            title: $.trim($(this).text())
                        };

                        $(this).data('eventObject', eventObject);

                        $(this).draggable({
                            zIndex: 999,
                            revert: true,
                            revertDuration: 0
                        });
                    });
                }
And finally we can implement drop functionality of the full calender plugin to accept the draggable events and we can achieve this by modifying the full calender jquery call as below-
            $('#calendar').fullCalendar({
                header: {
                    left: 'prev,next today',
                    center: 'title',
                    right: 'month,agendaWeek,agendaDay'
                },
                editable: true,
                droppable: true,
                drop: function(date, allDay) {

                    var originalEventObject = $(this).data('eventObject');

                    var copiedEventObject = $.extend({}, originalEventObject);

                    copiedEventObject.start = date;
                    copiedEventObject.allDay = allDay;

                    $('#calendar').fullCalendar('renderEvent', copiedEventObject, true);

                    if ($('#drop-remove').is(':checked')) {
                        $(this).remove();
                    }

                }
            });