<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>jQuery</title>
        <link>http://geekswithblogs.net/rajeshpillai/category/10965.aspx</link>
        <description>jquery learnings and experimits, tips tricks and cookbook...</description>
        <language>en-US</language>
        <copyright>Rajesh Pillai</copyright>
        <managingEditor>thinkrajesh@yahoo.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>jQuery 1.6.1 has been released</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2011/05/24/jquery-1-6-1-released.aspx</link>
            <description>&lt;p&gt;For more info refer the below post&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.jquery.com/2011/05/12/jquery-1-6-1-released/"&gt;http://blog.jquery.com/2011/05/12/jquery-1-6-1-released/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Some great improvements and fixes.&lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/145501.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2011/05/24/jquery-1-6-1-released.aspx</guid>
            <pubDate>Tue, 24 May 2011 06:05:22 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/145501.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2011/05/24/jquery-1-6-1-released.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/145501.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/145501.aspx</trackback:ping>
        </item>
        <item>
            <title>Free jQuery ebook online</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2010/06/27/free-jquery-ebook-online.aspx</link>
            <description>&lt;p&gt;jQuery fundametal online book  is available at &lt;a href="http://www.rebeccamurphey.com/jqfundamentals/book/release/html/"&gt;http://www.rebeccamurphey.com/jqfundamentals/book/release/html/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy :)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/140637.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2010/06/27/free-jquery-ebook-online.aspx</guid>
            <pubDate>Sun, 27 Jun 2010 13:39:40 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/140637.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2010/06/27/free-jquery-ebook-online.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/140637.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/140637.aspx</trackback:ping>
        </item>
        <item>
            <title>ASP.NET MVC Application In Action - I (DailyJournal)</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2010/05/21/mvcinaction.aspx</link>
            <description>&lt;p&gt;Its been long due I was planning to write an article on creating some useful ASP.NET MVC application. I have code named it "DailyJournal". Its a simple application which allows creation of multiple activities and assign tasks to these activities. Its' kind of "Yet another Task/Todo application". &lt;br /&gt;
&lt;br /&gt;
The credentials which you can use with the attached demo application is shown below. &lt;br /&gt;
&lt;br /&gt;
 &lt;/p&gt;
&lt;div id="premain0" class="small-text" style="width: 100%"&gt;&lt;img id="preimg0" src="http://www.codeproject.com/images/minus.gif" width="9" height="9" preid="0" style="cursor: pointer" alt="" /&gt;&lt;span id="precollapse0" preid="0" style="margin-bottom: 0px; cursor: pointer"&gt; Collapse&lt;/span&gt;&lt;img src="http://www.codeproject.com/images/copy_16.png" width="16" height="16" style="margin-left: 35px" alt="" /&gt;&lt;a href="#" preid="0"&gt; Copy Code&lt;/a&gt;&lt;/div&gt;
&lt;pre id="pre0" style="margin-top: 0px"&gt;
User Name : admin 
Password   : admin123
&lt;/pre&gt;
&lt;h2&gt;&lt;a id="heading0001" name="heading0001"&gt;Framework/Libraries Used&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;ASP.NET MVC&lt;/li&gt;
    &lt;li&gt;jQuery + jQuery UI (for ajax and UI)&lt;/li&gt;
    &lt;li&gt;ELMAH for Error logging&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a id="heading0002" name="heading0002"&gt;Warning Ahead&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is just a rough draft and so I am putting down some of the known limitation. &lt;br /&gt;
Some points of warning before we move further with this application. This is just an early prototype. As such many of the design principles have been ignored. But, I try to cover that up in the next update once I get my head around this.&lt;/p&gt;
&lt;p&gt;The application in its current state supports the following features&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Create users&lt;/li&gt;
    &lt;li&gt;Assign Activities to users&lt;/li&gt;
    &lt;li&gt;Assign tasks to activities&lt;/li&gt;
    &lt;li&gt;Assign a status to a task&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The user creation/authentication is being done by the default Membership provider. Most of the activities are highly visual i.e. you can drag-drop task to different areas, in-place edition of task details and so on.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;The following are the current issues with the design which I promise to refactor in the second version.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;No Validations&lt;/li&gt;
    &lt;li&gt;Fat Controller&lt;/li&gt;
    &lt;li&gt;XSS/CSS vulnerable&lt;/li&gt;
    &lt;li&gt;No Service model/abstraction yet. For the demo LINQ to SQL is implemented.&lt;/li&gt;
    &lt;li&gt;No separation of layers&lt;/li&gt;
    &lt;li&gt;UI Design&lt;/li&gt;
    &lt;li&gt;et el...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is just an extract.  For source code and more information proceed to&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codeproject.com/KB/aspnet/mvcinaction.aspx"&gt;http://www.codeproject.com/KB/aspnet/mvcinaction.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hope you like this!&lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/139983.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2010/05/21/mvcinaction.aspx</guid>
            <pubDate>Fri, 21 May 2010 02:27:44 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/139983.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2010/05/21/mvcinaction.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/139983.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/139983.aspx</trackback:ping>
        </item>
        <item>
            <title>jQuery 1.4 Released</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2010/01/17/jquery_1_4_released.aspx</link>
            <description>&lt;p&gt;jQuery 1.4 released.  You can find more info at http://api.jquery.com/category/version/1.4/&lt;/p&gt;
&lt;p&gt;Also celebrate jQuery 1.4 release with 14 days of jquery at &lt;a href="http://jquery14.com/pre-release-1"&gt;jquery14.com/pre-release-1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Learn about 15 new features of jQuery you must know &lt;a href="http://net.tutsplus.com/tutorials/javascript-ajax/jquery-1-4-released-the-15-new-features-you-must-know/"&gt;net.tutsplus.com/tutorials/javascript-ajax/jquery-1-4-released-the-15-new-features-you-must-know/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy jQuerying.....&lt;/p&gt;
&lt;p&gt; &lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/137518.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2010/01/17/jquery_1_4_released.aspx</guid>
            <pubDate>Sun, 17 Jan 2010 17:26:42 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/137518.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2010/01/17/jquery_1_4_released.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/137518.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/137518.aspx</trackback:ping>
        </item>
        <item>
            <title>jQuery Limit text entry</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/12/03/jqlimittext.aspx</link>
            <description>&lt;p&gt;Lets quickly have a look at how you can limit the entry to textbox and display the character input left to be keyed in.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;First things first, the script.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;
&amp;lt;script type="text/javascript"&amp;gt;
    $(function() {
        var limit = 250;
        $('#dvLimit').text('250 characters left');
        $('textarea[id$=txtDemoLimit]').keyup(function() {
            var len = $(this).val().length;
            if (len &amp;gt; limit) {
                this.value = this.value.substring(0, limit);
            }
            $("#dvLimit").text(limit - len + " characters left");
        });
    });
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The $() function does the following things on startup.&lt;/p&gt;
&lt;p&gt;1. Set a variable to a limit of 250 characters.&lt;/p&gt;
&lt;p&gt;2. Assign a default value to the "div" element with id "dvLimit"&lt;/p&gt;
&lt;p&gt;3. Find the control that contains the id "txtDemoLimit" and hook up the keyup event.&lt;/p&gt;
&lt;p&gt;4. In the keyup event get the length of the current text.&lt;/p&gt;
&lt;p&gt;5. If len is greater than the limit set, set the text value as a substring within the specified    limit.&lt;/p&gt;
&lt;p&gt;6. Update the div with the no. of characters left to be keyed in.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The HTML is shown below.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;
&amp;lt;div id="dvLimit"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;asp:TextBox ID="txtDemoLimit" TextMode="MultiLine" Columns = "40" Rows = "10" runat="server"&amp;gt;&amp;lt;/asp:TextBox&amp;gt;
&amp;lt;/div&amp;gt;

The following is the application in action.

&lt;img width="473" height="426" alt="Jquery text box limit demo" src="/images/geekswithblogs_net/rajeshpillai/demo.jpg" /&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Modify this as per your requiement and enjoy jQuerying !!!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;&lt;span class="code-keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="code-leadattribute"&gt;a&lt;/span&gt; &lt;span class="code-attribute"&gt;href&lt;/span&gt;&lt;span class="code-keyword"&gt;="&lt;/span&gt;&lt;span class="code-keyword"&gt;http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=48141" style="display:none"&lt;/span&gt; &lt;span class="code-attribute"&gt;rel&lt;/span&gt;&lt;span class="code-keyword"&gt;="&lt;/span&gt;&lt;span class="code-keyword"&gt;tag"&lt;/span&gt;&lt;span class="code-keyword"&gt;&amp;gt;&lt;/span&gt;&lt;span title="Or any of: 'code project', 'the code project', 'The Code Project'"&gt;CodeProject&lt;span class="code-keyword"&gt;&amp;lt;&lt;/span&gt;&lt;span class="code-keyword"&gt;/&lt;/span&gt;&lt;span class="code-leadattribute"&gt;a&lt;/span&gt;&lt;span class="code-keyword"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136674.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/12/03/jqlimittext.aspx</guid>
            <pubDate>Thu, 03 Dec 2009 12:10:31 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136674.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/12/03/jqlimittext.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136674.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136674.aspx</trackback:ping>
        </item>
        <item>
            <title>Lets build a simple blog engine - Prototype for Public Site [eboard]  - 3</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/11/28/eboard3.aspx</link>
            <description>&lt;h2&gt;Prototype&lt;/h2&gt;
&lt;p&gt;This time we will have a basic prototype ready for the public website.  The design will be kept simple so that we &lt;br /&gt;
could concentrate on the main task at hand.  Later on we will enable theming,so that the user could customize the &lt;br /&gt;
blog to their heart's content.&lt;/p&gt;
&lt;p&gt;The landing page looks like in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img width="600" height="491" alt="" src="/images/geekswithblogs_net/rajeshpillai/proto_0.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
Create a "Blog" folder under the "Views" folder in the website.  Add an aspx and copy the below markup and name it "List.aspx".  &lt;/p&gt;
&lt;pre&gt;&lt;p&gt;&amp;lt;%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage&amp;lt;IEnumerable&amp;lt;Eboard.Model.Blog&amp;gt;&amp;gt;" %&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"&amp;gt;&lt;br /&gt;    List&lt;br /&gt;&amp;lt;/asp:Content&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"&amp;gt;&lt;br /&gt;    &amp;lt;h2&amp;gt;You have &amp;lt;%= Model.Count() %&amp;gt; blogs created.&amp;lt;/h2&amp;gt;&lt;br /&gt;    &amp;lt;table&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;            &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;&lt;br /&gt;            &amp;lt;th&amp;gt;Created On&amp;lt;/th&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;% foreach (var item in Model) { %&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;%= Html.ActionLink("Edit", "Edit", new {  id=item.Id  }) %&amp;gt; |&lt;br /&gt;                &amp;lt;%= Html.ActionLink("Show", "Show", new {  id=item.Id  })%&amp;gt;&lt;br /&gt;            &amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;%= Html.Encode(item.Title) %&amp;gt;&lt;br /&gt;            &amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;%= Html.Encode(String.Format("{0:g}", item.CreatedOn)) %&amp;gt;&lt;br /&gt;            &amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;% } %&amp;gt;&lt;br /&gt;    &amp;lt;/table&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;&lt;br /&gt;        &amp;lt;%= Html.ActionLink("Create New", "Create") %&amp;gt;&lt;br /&gt;    &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/asp:Content&amp;gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;Create a "BlogController.cs" in the "Controller" folder and copy the following code.&lt;/p&gt;
&lt;p&gt; public ActionResult List()&lt;br /&gt;
 {&lt;br /&gt;
      ViewData["Message"] = "Welcome to Ebaord.  The minimalistic blogging engine!";&lt;br /&gt;
      return View();  // by default this returns a view with the name "List"&lt;br /&gt;
 }&lt;/p&gt;
&lt;p&gt;The above is just the boiler plate code just for reference.  The actual method will be implemented once we build our&lt;br /&gt;
repository and service layer.&lt;br /&gt;
&lt;br /&gt;
When the user click on the "Show" link the user will be taken to the home page of that blog.&lt;/p&gt;
&lt;p&gt;&lt;img width="650" height="532" alt="" src="/images/geekswithblogs_net/rajeshpillai/proto_1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
The final product may vary a bit as we go along. See you soon.  Happy prototyping....&lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136570.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/11/28/eboard3.aspx</guid>
            <pubDate>Fri, 27 Nov 2009 18:55:24 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136570.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/11/28/eboard3.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136570.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136570.aspx</trackback:ping>
        </item>
        <item>
            <title>jQuery Receipe : Build a simple pager plugin to use with asp.net mvc</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/jquerypager.aspx</link>
            <description>&lt;p&gt;Welcome back.   This time we will look at creating a simple jquery pager plugin to use with asp.net mvc project.  Please note the intent is to learn&lt;br /&gt;
the basics of jquery plugin development.  The control as such is not recommended for use in production environment. &lt;br /&gt;
&lt;br /&gt;
I recommend having a look at the jQuery Authoring Guideline at&lt;br /&gt;
&lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;docs.jquery.com/Plugins/Authoring&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Let's begin our journey into the mystery of jquery plugin.  The first step is to create a self executing anonymous function.  Anonymous functions play &lt;br /&gt;
a very important role in plugin development.  Lets dissect it.&lt;br /&gt;
&lt;br /&gt;
Let's have a look at the application in action.&lt;/p&gt;
&lt;p&gt;&lt;img width="800" height="584" alt="" src="/images/geekswithblogs_net/rajeshpillai/demo_1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;First let's understand the different way in which a function can be declared.&lt;/p&gt;
&lt;pre&gt;


Pattern 1

function hi() { 

    alert('say hi'); 

}

&lt;/pre&gt;
&lt;pre&gt;

Pattern 2

var hi = function() { 

    alert('say hi'); 

}

&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
The result of the above two function is the same.&lt;br /&gt;
hi();   // displays the alert&lt;br /&gt;
&lt;br /&gt;
Steps to invoke anonymous function&lt;/p&gt;
&lt;pre&gt;


    # original

    function hi() { alert('say hi'); }

    

    # step 1 

    # WRAP EVERYTHING IN () SO THAT WE HAVE A CONTEXT TO INVOKE THE FUNCTION

    &amp;gt; (function hi() { alert('say hi'); })

    

    # now call () to invoke this function

    &amp;gt; (function hi() { alert('say hi'); })();

&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
The final code is a bit awkward look for the uninitiated eye.  But, that is all anonymous function is all about.  With this understanding the &lt;br /&gt;
below code now seems to make sense.&lt;/p&gt;
&lt;pre&gt;

(function($) {

}) (jQuery);


In the above function we are passing "$" as the parameter to the anonymous function.  "$" in this case is 
jQuery object that is passed while invoking this function.


&lt;u&gt;A note about self executing anonymous function&lt;/u&gt;

Self-invoking functions are anonymous functions declared at run time and then invoke it immediately. Since 
they are anonymous functions they can’t be invoked twice. They are a good candidate for initialization work 
which is exactly what is happening in the jQuery plugin pattern.

Now let's quickly have a look at how we can extend the jQuery object.&lt;/pre&gt;
&lt;pre&gt;
    (function($) {
        $.fn.pager = function(url, callback, loadData) {
        }
    }) (jQuery);

jQuery offers a mechanism for adding in methods and functionality to the existing jQuery object.

$.fn.pager  (indicates we are extending the jQuery object witha pager function.

Let's move on.  Our function requires three parameter to function correclty.  The URL of the action method, 
the callback function to invoke and a boolean indicator whether to load data on first call or not.



Since jQuery should support muliple element we should wrap the call to our main function in an each() block.&lt;/pre&gt;
&lt;pre&gt;

(function($) {

    $.fn.pager = function(url, callback, loadData) {

        var cb = callback;

        var url = url;

        var element; // = $(this);

        this.each(function() {

            element = $(this);

            buildPager();

        });

        function buildPager() {

            var ht = '&amp;lt;table class="slickpager" style="margin-left:auto;margin-right:auto"&amp;gt;';
            ht += '&amp;lt;tr &amp;gt;';
            ht += '&amp;lt;td  id="prev" class="previous previous-off" &amp;gt;«&amp;lt;/td&amp;gt;';
            ht += '&amp;lt;td &amp;gt;';
            ht += 'Page &amp;lt;input type="text" style="width:30px" id="pageno" value="1"/&amp;gt; of &amp;lt;span id="totalpage"&amp;gt;10&amp;lt;/span&amp;gt;';
            ht += '&amp;lt;/td&amp;gt;';
            ht += '&amp;lt;td id="next" class="next next-on"&amp;gt;&amp;lt;a href="#"&amp;gt;»&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;   ';
            ht += '&amp;lt;/tr&amp;gt;';
            ht += '&amp;lt;/table&amp;gt;';
            element.html(ht);

            $("table.slickpager td", element).css("background-color", "#DAEAF6");

            $(element).css("background-color", "#DAEAF6");

            if (loadData) {
                var parameter = "pageNo=1";
                post(url, parameter, callback, "json");
            }
            else {

                attachPageEvents(url, cb);
            }
        }

}) (jQuery);

The buildPager() function creates the necessary HTML to generate the pager widget.  Me being lazy "pageNo"parameter is 
hardcoded. You can make it as a parameter to the function.  This parameter is passed to the URL to fetch paginated records.

The attachPageEvent() function hooks up the events for the "next", "previous" events.

function attachPageEvents(url, callback) {

    $("table.slickpager td a", element).unbind("click");

    $("table.slickpager td a", element).click(function(event) {
        event.preventDefault();
        var qs = getQueryString(this.href)["page"];
        var parameter = "pageno=" + qs;
        post(url, parameter, callback, "json");
    });

    $("table.slickpager input#pageno", element).unbind("blur");

    $("table.slickpager input#pageno", element).blur(function(event) {
        var pageno = $(this).val();
        var parameter = "pageno=" + pageno;
        post(url, parameter, callback, "json");
    });
}

&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
The post method is show below.  This function is important as it is here that the callback function that the client passed is invoked on success of the post.&lt;/p&gt;
&lt;pre&gt;


function post(url, parameter, callback, dataType) {

    $.ajax({

        type: "post",

        url: url,

        data: parameter,

        dataType: dataType,

        beforeSend: function(XMLHttpRequest) {

        },

        success: function(data) {

            updatePager(url, data);

            attachPageEvents(url, callback);



            if (typeof callback == 'function') {

                callback.call(this, data);

            }

        },

        error: function(msg) {

            alert("error : " + msg);

        },

        complete: function(XMLHttpRequest, textStatus) {

        }

    });

    }


The following block invokes the callback function.&lt;/pre&gt;
&lt;pre&gt;

if (typeof callback == 'function') {
    callback.call(this, data);
}


The updatePager() function updates the status of the pager control.&lt;/pre&gt;
&lt;pre&gt;
function updatePager(url, msg) {

    // set the prev text and link.
    $("table.slickpager td#prev", element).removeClass("previous-off").addClass("previous-on");

    var prevText = $("table.slickpager td#prev", element).text();

    var lnkPrev = "&amp;lt;a href='" + url + "?page=" + (msg.PageIndex - 1).toString() + "'&amp;gt;" + prevText + "&amp;lt;/a&amp;gt;";

    $("table.slickpager td#prev", element).html(lnkPrev);



    // set the next text and link.

    var nextText = $("table.slickpager tbody tr td#next", element).text();

    var lnkNext = "&amp;lt;a href='" + url + "?page=" + (msg.PageIndex + 1).toString() + "'&amp;gt;" + nextText + "&amp;lt;/a&amp;gt;";



    $("table.slickpager td#next", element).removeClass("next-off").addClass("next-on");

    $("table.slickpager td#next", element).html(lnkNext);



    $("table.slickpager input#pageno", element).val(msg.PageIndex);

    $("table.slickpager td span#totalpage", element).text(msg.TotalPages.toString());



    if (!msg.HasPreviousPage) {

        var prevText = $("table.slickpager td#prev", element).text();

        $("table.slickpager td#prev", element).html(prevText);

        $("table.slickpager td#prev").removeClass("previous").addClass("previous-off");

    }

    if (!msg.HasNextPage) {

        var nextText = $("table.slickpager td#next", element).text();

        $("table.slickpager td#next", element).html(nextText);

        $("table.slickpager td#next", element).removeClass("next").addClass("next-off");

    }

}



There are some optimizations which we could do.  I may possibly highlight that in another blog post.
Now comes the most important part.&lt;/pre&gt;
&lt;pre&gt;

    return this;


Invoke this statement at the end of all the function.  This will keep the jQuery design
of chainability of objects intact.



To use this pager component in your page

&amp;lt;script type="text/javascript"&amp;gt;

    $(function() {

        $("#pager-demo").pager("/home/GetRandomData", callback, true);

    });



    function callback(msg) {

        if (msg == null)

            return false;

        

        if (msg.Items.length &amp;gt; 0) {

            var data = "&amp;lt;table border='0' width='100%'&amp;gt;"

            data += "&amp;lt;thead&amp;gt;&amp;lt;tr&amp;gt;";

            data += "&amp;lt;th&amp;gt;Book Name&amp;lt;/th&amp;gt;";

            data += "&amp;lt;th&amp;gt;Tag&amp;lt;/th&amp;gt;";

            data += "&amp;lt;/tr&amp;gt;&amp;lt;/thead&amp;gt;";

            $(msg.Items).each(function() {

                data += "&amp;lt;tr&amp;gt;";

                data += "&amp;lt;td&amp;gt;&amp;lt;a href='#'&amp;gt;" + this.BookName + "&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;" + this.Tag + "&amp;lt;/td&amp;gt;";

            });

            data += "&amp;lt;/table&amp;gt;";

            //alert(data);

            $("div#content").html(data);

        }

        else {

            $("div#content").html("&amp;lt;i&amp;gt;There are no books to be displayed.&amp;lt;/i&amp;gt;");

        }

    }

&amp;lt;/script&amp;gt;

&amp;lt;/pre&amp;gt;

Modify the callback method as per your requirement.  The HTML markup is shown below.

&lt;pre&gt;


&amp;lt;div id="widget"&amp;gt;

    &amp;lt;div id="content"&amp;gt;&amp;lt;/div&amp;gt;

    &amp;lt;div id="pager-demo"&amp;gt;

    &amp;lt;/div&amp;gt;

&amp;lt;/div&amp;gt;

&amp;lt;/pre&lt;p&gt; &lt;/p&gt;
&lt;p&gt;For reference the css is given below&lt;/p&gt;
&lt;p&gt;.slickpager a{&lt;br /&gt;&lt;br /&gt;    border:solid 1px #9aafe5;&lt;br /&gt;&lt;br /&gt;    margin-right:2px;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.slickpager .previous-off, .slickpager .next-off {&lt;br /&gt;&lt;br /&gt;    border:solid 1px #DEDEDE;&lt;br /&gt;&lt;br /&gt;    color:#888888;&lt;br /&gt;&lt;br /&gt;    display:block;&lt;br /&gt;&lt;br /&gt;    float:left;&lt;br /&gt;&lt;br /&gt;    font-weight:bold;&lt;br /&gt;&lt;br /&gt;    margin-right:2px;&lt;br /&gt;&lt;br /&gt;    padding:3px 4px;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.slickpager .next a, .slickpager .previous a {&lt;br /&gt;&lt;br /&gt;    font-weight:bold;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.slickpager .active{&lt;br /&gt;&lt;br /&gt;    background:#2e6ab1;&lt;br /&gt;&lt;br /&gt;    color:#FFFFFF;&lt;br /&gt;&lt;br /&gt;    font-weight:bold;&lt;br /&gt;&lt;br /&gt;    display:block;&lt;br /&gt;&lt;br /&gt;    float:left;&lt;br /&gt;&lt;br /&gt;    padding:4px 6px;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.slickpager a:link, .slickpager a:visited {&lt;br /&gt;&lt;br /&gt;    color:#0e509e;&lt;br /&gt;&lt;br /&gt;    display:block;&lt;br /&gt;&lt;br /&gt;    float:left;&lt;br /&gt;&lt;br /&gt;    padding:3px 6px;&lt;br /&gt;&lt;br /&gt;    text-decoration:none;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.slickpager a:hover{&lt;br /&gt;&lt;br /&gt;     border:solid 1px #0e509e&lt;br /&gt;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;And here's the entire source code for jquery.slickpager.js&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;
(function($) {
    $.fn.pager = function(url, callback, loadData) {
        var cb = callback;
        var url = url;
        var element; // = $(this);

        this.each(function() {
            element = $(this);
            buildPager();
        });

        function buildPager() {
            var ht = '&amp;lt;table class="slickpager" style="margin-left:auto;margin-right:auto"&amp;gt;';
            ht += '&amp;lt;tr &amp;gt;';
            ht += '&amp;lt;td  id="prev" class="previous previous-off" &amp;gt;«&amp;lt;/td&amp;gt;';
            ht += '&amp;lt;td &amp;gt;';
            ht += 'Page &amp;lt;input type="text" style="width:30px" id="pageno" value="1"/&amp;gt; of &amp;lt;span id="totalpage"&amp;gt;10&amp;lt;/span&amp;gt;';
            ht += '&amp;lt;/td&amp;gt;';
            ht += '&amp;lt;td id="next" class="next next-on"&amp;gt;&amp;lt;a href="#"&amp;gt;»&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;   ';
            ht += '&amp;lt;/tr&amp;gt;';
            ht += '&amp;lt;/table&amp;gt;';

            element.html(ht);

            $("table.slickpager td", element).css("background-color", "#DAEAF6");

            $(element).css("background-color", "#DAEAF6");

            if (loadData) {
                var parameter = "pageNo=1";
                post(url, parameter, callback, "json");
            }
            else {
                attachPageEvents(url, cb);
            }
        }

        function attachPageEvents(url, callback) {
            $("table.slickpager td a", element).unbind("click");
            $("table.slickpager td a", element).click(function(event) {
                event.preventDefault();
                var qs = getQueryString(this.href)["page"];
                var parameter = "pageno=" + qs;
                post(url, parameter, callback, "json");
            });

            $("table.slickpager input#pageno", element).unbind("blur");

            $("table.slickpager input#pageno", element).blur(function(event) {
                var pageno = $(this).val();
                var parameter = "pageno=" + pageno;
                post(url, parameter, callback, "json");
            });
        }

        function post(url, parameter, callback, dataType) {
            $.ajax({
                type: "post",
                url: url,
                data: parameter,
                dataType: dataType,
                beforeSend: function(XMLHttpRequest) {
                    //$(element).html('&amp;lt;img id="loader-img" src="/Images/ajax-loader.gif" /&amp;gt;');
                },
                success: function(data) {
                    updatePager(url, data);
                    attachPageEvents(url, callback);

                    if (typeof callback == 'function') {
                        callback.call(this, data);
                    }
                },
                error: function(msg) {
                    alert("error : " + msg);
                },
                complete: function(XMLHttpRequest, textStatus) {
                }
            });
        }

        function getQueryString(href) {
            var assoc = new Array();

            if (href != '') {
                var queryString = unescape(href.substring(1));
                queryString = unescape(href.substring(href.lastIndexOf("?") + 1));
            }
            else {
                var queryString = unescape(location.search.substring(1));
            }

            var keyValues = queryString.split('&amp;amp;');
            for (var i in keyValues) {
                var key = keyValues[i].split('=');
                assoc[key[0]] = key[1];
            }
            return assoc;
        }

        function updatePager(url, msg) {
            // set the prev text and link.

            $("table.slickpager td#prev", element).removeClass("previous-off").addClass("previous-on");

            var prevText = $("table.slickpager td#prev", element).text();

            var lnkPrev = "&amp;lt;a href='" + url + "?page=" + (msg.PageIndex - 1).toString() + "'&amp;gt;" + prevText + "&amp;lt;/a&amp;gt;";
            $("table.slickpager td#prev", element).html(lnkPrev);


            // set the next text and link.
            var nextText = $("table.slickpager tbody tr td#next", element).text();
            var lnkNext = "&amp;lt;a href='" + url + "?page=" + (msg.PageIndex + 1).toString() + "'&amp;gt;" + nextText + "&amp;lt;/a&amp;gt;";


            $("table.slickpager td#next", element).removeClass("next-off").addClass("next-on");
            $("table.slickpager td#next", element).html(lnkNext);

            $("table.slickpager input#pageno", element).val(msg.PageIndex);
            $("table.slickpager td span#totalpage", element).text(msg.TotalPages.toString());

            if (!msg.HasPreviousPage) {
                var prevText = $("table.slickpager td#prev", element).text();
                $("table.slickpager td#prev", element).html(prevText);
                $("table.slickpager td#prev").removeClass("previous").addClass("previous-off");
            }
            if (!msg.HasNextPage) {
                var nextText = $("table.slickpager td#next", element).text();
                $("table.slickpager td#next", element).html(nextText);
                $("table.slickpager td#next", element).removeClass("next").addClass("next-off");
            }
        }
        return this;
    }
})(jQuery);
&lt;/pre&gt;
&lt;p&gt;Hope you enjoyed this blog post.  I'll soon post the source link to this blog.&lt;/p&gt;
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136563.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/jquerypager.aspx</guid>
            <pubDate>Fri, 27 Nov 2009 07:11:05 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136563.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/jquerypager.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136563.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136563.aspx</trackback:ping>
        </item>
        <item>
            <title>Lets build a simple blog engine [eboard] - 2</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/blogengine2.aspx.aspx</link>
            <description>&lt;p&gt;Welcome to the 2nd series of building a blog engine.  In the first part we have laid out the foundation for this application and modeled the DB  structure for quick mockup.&lt;/p&gt;
&lt;p&gt;You can read the first part here &lt;a href="http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/lets-build-a-simple-blog-engine-eboard---1.aspx"&gt;lets-build-a-simple-blog-engine-eboard---1.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One thing I missed to mentioned in the first part is the we will be using the excellent ELMAH for error logging.  This is a pretty cool module which hooks up to the system &lt;br /&gt;
and logs all exceptions without writing a single line of code.&lt;/p&gt;
&lt;p&gt;You can read more about ELMAH at &lt;a href="http://code.google.com/p/elmah/"&gt;code.google.com/p/elmah/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What we will be doing is creating the public facing website first rather than creating the administration screens.  We will decide upon the themes to use and mockup a &lt;br /&gt;
quick prototype for the public view.&lt;/p&gt;
&lt;p&gt;The following the is the project structure I came up with.  This is just skeleton and the meat will be added incrementally over next couple of weeks.&lt;/p&gt;
&lt;h3&gt;Project Structure &lt;/h3&gt;
&lt;p&gt;&lt;img width="702" height="601" src="/images/geekswithblogs_net/rajeshpillai/folder_structure_1.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I have divided the project according to the responsibility of each component.  As you can see we will be using the LinqToSql along with the Repository pattern for &lt;br /&gt;
data access.  This will provide us with the flexibility to switch data provider at will and also provides the principle of OCP (Open for Extension and Closed for Modification).&lt;/p&gt;
&lt;p&gt;I prefer to keep the model in a separate project rather than keeping it along with the web project.  For this project the controllers wil be lying in the default "Controllers" folder.&lt;/p&gt;
&lt;p&gt;We will also change the layout of the "Content" folder.  The content folder is where all your css are kept.  We will take a different approach possibly to enable easy theming &lt;br /&gt;
of our blogs.&lt;/p&gt;
&lt;p&gt;Watch for the next post, where we will be mocking up the public site for the blog.  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136559.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/blogengine2.aspx.aspx</guid>
            <pubDate>Thu, 26 Nov 2009 20:17:50 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136559.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/blogengine2.aspx.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136559.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136559.aspx</trackback:ping>
        </item>
        <item>
            <title>Lets build a simple blog engine [eboard] - 1</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/eboard1.aspx</link>
            <description>&lt;h2&gt;Welcome to eBoard&lt;/h2&gt;
&lt;p&gt;Hello and welcome to this series of application development using asp.net mvc, jquery, automapper, ninject.  Though the world doesn't need another blog engine, but sometimes reinventing the &lt;br /&gt;
wheel teaches you many unknown things and it's the learning experinece that counts more than anything else.&lt;/p&gt;
&lt;p&gt;I have been using asp.net mvc + jquery for about a year now.  So, it's time to put down something which will help the beginner with this technologies get a good graps of the fundamentals skill required &lt;br /&gt;
to do web development. &lt;/p&gt;
&lt;p&gt;The side effect of this is we will also learn about some design principles, best practices and troubleshooting will add icing to the cake.&lt;/p&gt;
&lt;p&gt;Without further ado, lets begin.  Let's first lay down the basic business requirement for the blog engine.  This may be simple in form, but will help us keep an eye on the actual requirement and prevent &lt;br /&gt;
us from deviating from the main goal.&lt;/p&gt;
&lt;p&gt;The blog engine will be named as "eboard".&lt;/p&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;ol&gt;
    &lt;li&gt;Multi blog support : The user should be able to create multiple blogs.&lt;/li&gt;
    &lt;li&gt;Make posts&lt;/li&gt;
    &lt;li&gt;Assign a category to the post&lt;/li&gt;
    &lt;li&gt;Assing one or more tags to the post&lt;/li&gt;
    &lt;li&gt;Allow readers to post comment&lt;/li&gt;
    &lt;li&gt;Comment Moderation&lt;/li&gt;
    &lt;li&gt;Simple Blog Settings like theme selection.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Apart from creating a working blog engine the following are educational/learning benefit the reader may derive from this experience&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Learn asp.net mvc and jquery&lt;/li&gt;
    &lt;li&gt;Learn to design/extend a validation framework&lt;/li&gt;
    &lt;li&gt;Learn about Repository pattern&lt;/li&gt;
    &lt;li&gt;Learn dependency injection using Ninject.&lt;/li&gt;
    &lt;li&gt;Service design&lt;/li&gt;
    &lt;li&gt;Design for testability (though we won't be writing test at this point in time).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the above requirements in mind lets move ahead a take a shot at creating the database for our blog.   Some of the reader may frown at this idea.  Designing the database first or the model first is akin to &lt;br /&gt;
the chicken and the hen problem.  But for this small application I think the database design will closely mimic the model as well.  Please free to shout at me if you feel anything is terribly wrong here.&lt;/p&gt;
&lt;p&gt;The initial DB model looks like the figure shown below.&lt;br /&gt;
 &lt;/p&gt;
&lt;h3&gt;DB Model&lt;/h3&gt;
&lt;p&gt;&lt;img width="700" height="468" alt="" src="/images/geekswithblogs_net/rajeshpillai/db_1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;We are using the membership provider for users and roles. The above DB model gives us a good start in designing our blog.  It has all the essential elements to support the business &lt;br /&gt;
requirement that we have laid out for "eboard".&lt;/p&gt;
&lt;p&gt;The below table highlights the essential details about the above model.&lt;/p&gt;
&lt;table cellspacing="1" cellpadding="1" border="1" style="width: 829px; height: 168px;"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;BlogSettings&lt;/td&gt;
            &lt;td&gt;This stores the essential settings related to blog.  Curently it has only the name of the theme and comment moderation flag.  This can be extended as required.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Blog&lt;/td&gt;
            &lt;td&gt;This allows us to have multiple blog created.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Post&lt;/td&gt;
            &lt;td&gt;The posts that goes with the blog.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Comment&lt;/td&gt;
            &lt;td&gt;The comments that goes with the post.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Category&lt;/td&gt;
            &lt;td&gt;A post can belong to only one category.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Tags&lt;/td&gt;
            &lt;td&gt;A post can hve multiple tag.  Tags are useful for search.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt; &lt;/td&gt;
            &lt;td&gt; &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That's it for this episode.  In the next episode we will layout the folder structure for the "eboard" application.  Till then happy learning and enjoy blogging.&lt;/p&gt;
&lt;p&gt;&lt;a style="display: none;" rel="tag" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid= 48141"&gt;CodeProject&lt;/a&gt;&lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136557.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/eboard1.aspx</guid>
            <pubDate>Thu, 26 Nov 2009 18:47:59 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136557.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/11/27/eboard1.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136557.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136557.aspx</trackback:ping>
        </item>
        <item>
            <title>In-Place-Edit with jQuery</title>
            <link>http://geekswithblogs.net/rajeshpillai/archive/2009/11/26/in-place-edit-with-jquery.aspx</link>
            <description>&lt;p&gt;Let's try a simple in-place edit with jquery.  For demonstration purpose I am using the plain old HTML file.  However, &lt;br /&gt;
if you, wish you could apply the same technique to asp.net, asp.net mvc or php or any other web application as well.&lt;/p&gt;
&lt;p&gt; Here is the html that we will be using for the demo.&lt;/p&gt;
&lt;p&gt;&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;div style="line-height:3xm;background-color:skyblue"&amp;gt; &lt;br /&gt;
        Double Click the below paragraph to edit.&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/br&amp;gt;&amp;lt;/br&amp;gt;&lt;br /&gt;
    &amp;lt;div class="edit"&amp;gt;&lt;br /&gt;
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. &lt;br /&gt;
        Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis &lt;br /&gt;
        sagittis ipsum. Praesent mauris. &lt;br /&gt;
        Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. &lt;br /&gt;
        Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. &lt;br /&gt;
        Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. &lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p&gt;The element that needs to be made editable is given a class  of "edit".&lt;br /&gt;
 &lt;/p&gt;
&lt;p&gt;The following is the minimal CSS we will be using for this demo.&lt;/p&gt;
&lt;div style="background-color: rgb(251, 237, 187);"&gt;
&lt;p&gt;&amp;lt;style type="text/css"&amp;gt;&lt;br /&gt;
        .edit {&lt;br /&gt;
            width:400px;&lt;br /&gt;
            border:1px dashed orange;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        .saveButton {&lt;br /&gt;
        }&lt;br /&gt;
        .cancelButton {&lt;br /&gt;
        }&lt;/p&gt;
&lt;p&gt; &amp;lt;/style&amp;gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Let's add a reference to the jquery library&lt;/p&gt;
&lt;p&gt;If you have a local copy then refer it as follows&lt;/p&gt;
&lt;pre&gt;
&amp;lt;script src="scripts/jquery-1.3.2.min.js"&amp;gt;&amp;lt;/script&amp;gt; 
&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
The above assumes you have a copy of the jquery library in the scripts folder on your root directory.&lt;/p&gt;
&lt;p&gt;Otherwise you can always grab the latest copy from google..&lt;/p&gt;
&lt;pre&gt;
&amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Now let's setup the event handler to make the div editable.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div style="background-color: rgb(251, 237, 187);"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;
  $(function(){&lt;br /&gt;
            setEditable();&lt;br /&gt;
  });&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;/div&gt;
&lt;p&gt;The $() function is jquery's way of telling the browser to execte the function when the DOM is ready.&lt;/p&gt;
&lt;p&gt;Here' is the setEditable function.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div style="background-color: rgb(251, 237, 187);"&gt;function setEditable() {&lt;br /&gt;
    $('.edit').click(function() {&lt;br /&gt;
          var textarea = '&amp;lt;div&amp;gt;&amp;lt;textarea&amp;gt;'+$(this).html()+'&amp;lt;/textarea&amp;gt;';&lt;br /&gt;
           var button     = '&amp;lt;div&amp;gt;&amp;lt;input type="button" value="SAVE" class="saveButton" /&amp;gt; &amp;lt;input type="button" value="CANCEL" class="cancelButton" /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;';&lt;br /&gt;
                var revert = $(this).html();&lt;br /&gt;
                $(this).after(textarea+button).remove();&lt;br /&gt;
                $('.saveButton').click(function(){saveChanges(this, false);});&lt;br /&gt;
                $('.cancelButton').click(function(){saveChanges(this, revert);});&lt;br /&gt;
            })&lt;br /&gt;
  };&lt;/div&gt;
&lt;div style="background-color: rgb(251, 237, 187);"&gt;&lt;br /&gt;
  function trim(stringToTrim) {&lt;br /&gt;
       return stringToTrim.replace(/^\s+|\s+$/g, "");&lt;br /&gt;
  }&lt;/div&gt;
&lt;p&gt;The above function essentially does three things.&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Hook up the click event handler on the element with class ".edit".&lt;/li&gt;
    &lt;li&gt;Inside the function the following are the sequence that happens
    &lt;ol&gt;
        &lt;li&gt;Build the html for inserting a &amp;lt;textarea&amp;gt; for editing.&lt;/li&gt;
        &lt;li&gt;Build the html for inserting a "save" and "cancel" button.&lt;/li&gt;
        &lt;li&gt;Save the current value of the element.&lt;/li&gt;
        &lt;li&gt;Removes the current div (with class .edit) and inserts the above html.&lt;/li&gt;
        &lt;li&gt;Hooks up the events for "save" and "cancel" button.&lt;/li&gt;
    &lt;/ol&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;br /&gt;
&lt;span style="background-color: rgb(153, 204, 255);"&gt;  Note: the jquery function after() inserts content after each of the matched elements.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; The below function is called when you click "save" or "cancel" button&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div style="background-color: rgb(251, 237, 187);"&gt;&lt;br /&gt;
function saveChanges(obj, cancel) {&lt;br /&gt;
      if (!cancel) {&lt;br /&gt;
            var newValue = $(obj).parent().siblings(0).val();&lt;br /&gt;
            if(trim(newValue) == '') newValue = '(click to add text)';&lt;br /&gt;
      }&lt;br /&gt;
      else {&lt;br /&gt;
            newValue = cancel;&lt;br /&gt;
            if(trim(newValue) == '') newValue = '(click to add text)';&lt;br /&gt;
       }&lt;br /&gt;
            &lt;br /&gt;
      $(obj).parent().parent().after('&amp;lt;div class="edit"&amp;gt;' +  newValue +'&amp;lt;/div&amp;gt;').remove();&lt;br /&gt;
      setEditable();&lt;br /&gt;
}&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;That's it.  You can actually make an ajax request and send this data to the server for persistence.  We will see &lt;br /&gt;
that in an another post.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt; &lt;img src="http://geekswithblogs.net/rajeshpillai/aggbug/136550.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rajesh Pillai</dc:creator>
            <guid>http://geekswithblogs.net/rajeshpillai/archive/2009/11/26/in-place-edit-with-jquery.aspx</guid>
            <pubDate>Thu, 26 Nov 2009 07:24:42 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/rajeshpillai/comments/136550.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/rajeshpillai/archive/2009/11/26/in-place-edit-with-jquery.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/rajeshpillai/comments/commentRss/136550.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/rajeshpillai/services/trackbacks/136550.aspx</trackback:ping>
        </item>
    </channel>
</rss>
