jQuery and MVC–Part 4, now with Wijmo!

By James at December 17, 2010 11:04
Filed Under: JavaScript, jQuery, jQuery Plugins, Wijmo

In part three of this series I talked about how to extend jQuery with plugins, went through the steps of writing a plugin, and then demonstrated how to use it in a standard HTML page. I showed you a popular Table Sorter plugin and showed how to initialize it with different options. In this last article I will show you one more plugin, the Wijmo Grid, and how easy it easy to implement it’s different options and features. I will also show you some of the cool things that Wijmo can do to help spruce up your web forms and pages.

Going back to the Student Course Admin form I’ve been using for these articles, I am generating a table of student data in an ASP.NET MVC app.

7563.image_281CC156

One thing I did add since the last article was the ability to filter the students by their first or last name.

4186.image_2BDA6626

3666.image_43919D8C

This was done by adding some JavaScript and an Ajax call which gets a new set of data from the server, then replaces the original table with the new table.

   1: function getStudentsByName(elem) {
   2:     $("img.ajaxLoaderFName").fadeOut(500);
   3:     $("img.ajaxLoaderLName").fadeOut(500);
   4:     var $elem = $(elem);
   5:     var url = "";
   6:     var ajaxLoader;
   7:     if ($elem.attr("id") == "txtFilterFName") {
   8:         url = "/Home/GetStudentsByFirstName/" + $elem.val();
   9:         ajaxLoader = $("img.ajaxLoaderFName");
  10:     }
  11:     if ($elem.attr("id") == "txtFilterLName") {
  12:         url = "/Home/GetStudentsByLastName/" + $elem.val();
  13:         ajaxLoader = $("img.ajaxLoaderLName");
  14:     }
  15:     
  16:     ajaxLoader.fadeIn(500);
  17:     $.ajax({
  18:         url: url,
  19:         type: "GET",
  20:         success: function (result) {
  21:             var holder = $("table.studentTable").parent("div.row");
  22:             $("table.studentTable").remove();
  23:             holder.html(result);
  24:             ajaxLoader.fadeOut(500);
  25:             $("div.chkGraphic").graphicCheckBox();
  26:         }
  27:     });
  28: }

Pretty standard stuff by now, but it can be made a whole lot better by using Wijmo. Let’s see how to do that.

Wijmo

Wijmo is a new product, complete kit of over 30 jQuery UI Widgets. It is a mixture of jQuery, CSS3, SVG, and HTML5. You can download it at www.wijmo.com.

The Wijmo grid has 20 different options that you can mix and match to make your grid look and behave how you would like. Detailed information about these options can be found at http://wijmo.com/wiki/index.php/Grid#ui.wijgrid_Options. For this demo, I am going to setup the grid with the following options: allowSorting, allowColumnSizing, allowPaging, and setting the page size to 10 rows.

As I mentioned before, when adding the references to your JavaScript files, the order of each reference is very important. After you download Wijmo, there will be several JavaScript files which will need to be included in your page.

   1: <script type="text/javascript" 
   2:   src="[Path]/Wijmo-Open/development-bundle/external/
   3:   jquery-1.4.3.min.js"></script>
   4:  
   5: <script type="text/javascript" 
   6:   src="[Path]/Wijmo-Open/development-bundle/external/
   7:   jquery-ui-1.8.6.custom.min.js"></script>
   8:  
   9: <script type="text/javascript" 
  10:   src="[Path]/Wijmo-Open/development-bundle/external/
  11:   jquery.bgiframe-2.1.3-pre.js"></script>
  12:  
  13: <script type="text/javascript" 
  14:   src="[Path]/Wijmo-Open/development-bundle/external/
  15:   jquery.glob.min.js"></script>
  16:  
  17: <script type="text/javascript" 
  18:   src="[Path]/Wijmo-Complete/development-bundle/external/
  19:   jquery.mousewheel.min.js"></script>
  20:  
  21: <script type="text/javascript" 
  22:   src="[Path]/Wijmo-Complete/development-bundle/external/
  23:   jquery.tmpl.min.js"></script>
  24:  
  25: <script type="text/javascript" 
  26:   src="[PathToJavaScript]/Wijmo-Complete/development-bundle/external/
  27:   raphael.js"></script>
  28:  
  29: <script type="text/javascript" 
  30:   src="[PathToJavaScript]/Wijmo-Open/js/
  31:   jquery.wijmo-open.1.0.0.min.js"></script>
  32:  
  33: <script type="text/javascript" 
  34:   src="[PathToJavaScript]/Wijmo-Complete/js/
  35:   jquery.wijmo-complete.1.0.0.min.js"></script>

You will also need to reference the Wijmo style sheets as well.

   1: <link href=”[Path]/Wijmo-Complete/development-bundle/themes/
   2:   ui-lightness/jquery-ui-1.8.4.custom.css" rel=”stylesheet
   3:   type=”text/css/>
   4:  
   5: <link href=”[Path]/Wijmo-Open/css/jquery.wijmo-open.1.0.0.css" 
   6:   rel=”stylesheettype=”text/css/>
   7:  
   8: <link href=”[Path]/Wijmo-Complete/css/jquery.wijmo-complete.1.0.0.css" 
   9:   rel=”stylesheettype=”text/css/>

Initializing the Wijmo grid is done the same way you do other things in jQuery, by getting an element in the page, in this case the table with an ID of “studentTable”, then adding the jQuery plugin to the element.

   1: $("#studentTable").parent().wijgrid({ 
   2:     allowSorting: true, 
   3:     allowColSizing: true, 
   4:     allowPaging: true, 
   5:     pageSize: 10 
   6: });

Here is the result.

0027.image_27A06894

As you can see the graphical check buttons I talked about in the last article are still there, and the grid has a nifty pager at the bottom.

The allowSorting option adds sorting capability on each column as seen here.

4578.image_52985699

While the “allowColSizing” lets you adjust the widths of each column to better view your data.

1300.image_1A9662B6

Another great option with the Wijmo grid is to allow editing to your data. In the jQuery to initialize the Wijmo grid, add another option, allowEditing:true.

   1: $("#studentTable").wijgrid({ 
   2:     allowSorting: true, 
   3:     allowColSizing: true, 
   4:     allowPaging: true, 
   5:     pageSize: 10, 
   6:     allowEditing: true 
   7: });

When the grid is rendered, each table cell will now become editable. All you have to do is click in the cell and start making any changes you need. The Wijmo Grid exposes events so you can handle the changed data however you prefer to.

There are 15 events total in the Wijmo Grid, and details on each of them are at http://wijmo.com/wiki/index.php/Grid#ui.wijgrid_Events. The Wijmo grid is very feature rich and I would highly recommend you play around with it.

Other Wijmo goodies

No more do you have to deal with boring old form elements on your page. Wijmo has decorators for Radio Buttons, Checkboxes, Drop Downs and Text fields. Adding these decorators is as easy as adding an additional jQuery call to your selected element.

So, by adding the following to my text fields which filter by student name.

   1: $("input#txtFilterFName").focus(function () { 
   2:     $("input#txtFilterLName").val(""); }).keyup(function () { 
   3:     getStudentsByName(this); }).wijtextboxdecorator();
   4:  
   5: $("#chkPaging").wijcheckboxdecorator();
   6:     $("#txtPageSize").wijtextboxdecorator();
   7:     $("input[type=radio]").wijradiobuttondecorator();

I get these spiffy looking text fields and form elements.

7484.image_52F463C1

One thing you may have noticed is that the grid and the form elements all have the same theme. This is because of the jQuery UI theming that is built into Wijmo. If you don’t like how the elements look you can create your own themes with the jQuery UI Theme Roller at http://jqueryui.com/themeroller/. When you get your theme just how you want it to, all it takes is a download, and referencing your theme’s particular style sheet in your page.

7026.image_43051EFD

   1: <link href="[Path]/Content/ui-lightness/jquery-ui-1.8.4.custom.css"
   2:     rel="stylesheet" type="text/css" />

In this article we talked more about jQuery plugins, the Wijmo gallery of widgets and how they can be used to create dynamic and very professional looking web applications. I hope you have enjoyed this series and have learned a few tricks. And as always, I would love to read your comments on my blog.

Happy Programming,

James

jQuery and MVC–Part 3

By James at November 19, 2010 19:11
Filed Under: JavaScript, MVC, jQuery, jQuery Plugins

In the last article I talked about MVC and doing some nifty Ajax functionalities with jQuery. In this article I will go over jQuery plugins, what they are and how to create them.

jQuery Plugins

jQuery has a plugin architecture which allows you to package up commonly used functions into a plugin. Chances are if you have a complex JavaScript function, someone has more than likely written a plugin to handle that particular functionality. The jQuery.com site has an extensive plugin library and it can sometimes be fun to browse through it to see what people have come up with.

Plugins are fairly easy to write, once you have gotten the basics of jQuery down. Here is a tooltip plugin that I wrote in just a few minutes.

   1: (function ($) {
   2:     $.fn.tooltip = function (options) { // make sure to name the function
   3:                                         // the same as your tooltip
   4:         var methods = {
   5:             
   6:             //initialize stuff
   7:             init: function (options) { },
   8:             
   9:             //destroy and clean up
  10:             destroy: function () {
  11:                 return this.each(function () {
  12:                     $(window).unbind("tooltip");
  13:                 })
  14:             }
  15:         };
  16:  
  17:         // default settings if they aren't passed in
  18:         var settings = {
  19:             'backgroundColor': 'red',
  20:             'color': 'blue',
  21:             'toolTipText': 'Hi',
  22:             'fontWeight': 'bold'
  23:         };
  24:  
  25:         // add the settings into the options
  26:         return this.each(function () {
  27:             if (options) {
  28:                 $.extend(settings, options);
  29:             }
  30:  
  31:             var $this = $(this);
  32:             $this.mouseenter(function (event) {
  33:                 $this.css("color", settings.colorEnter);
  34:                 
  35:                 // if the div#toolTip isn't in the DOM, create a new one
  36:                 if (!$("#toolTip").length) {
  37:                     // create the element
  38:                     $('<div id="toolTip"></div>')
  39:                         // set the text to passed option
  40:                         .html(settings.toolTipText)
  41:                         // from the style sheet
  42:                         .addClass("toolTip")
  43:                         // insert the div into the DOM just after $this
  44:                         .insertAfter($this)
  45:                         // position the div
  46:                         .css({ "left": $this.width(),
  47:                         // set the backgroundColor
  48:                         "backgroundColor": settings.backgroundColor,
  49:                         // set the font
  50:                         "fontWeight": settings.fontWeight,
  51:                         // set the color
  52:                         "color": settings.color
  53:                     }); 
  54:                 }
  55:                 $("#toolTip").fadeIn(500);
  56:             });
  57:  
  58:             $this.mouseleave(function () {
  59:                 $this.css("color", settings.colorLeave);
  60:                 $("#toolTip").fadeOut(500);
  61:             });
  62:         });
  63:     };
  64: })(jQuery);

It’s not a pretty thing, or even that functional, but it does show off how fast you can write a plugin. Let’s take a look at how this plugin is implemented.

1. In the <head> tag of your page include the references to your jQuery and JavaScript files.

   1: <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
   2: <script src="Scripts/jquery.tooltip.js" type="text/javascript"></script>
   3: <script src="Scripts/AppScripts.js" type="text/javascript"></script>

2. Somewhere on your page add an element that will call the plugin

   1: <div class="test">This is the element that will have the assignment</div>

3. In your custom JavaScript, attach the plugin to the element and pass in any options you need to.

   1: $(document).ready(function () {
   2:     $("div.test").tooltip({ "toolTipText": "Hello from ComponentOne", 
   3:         "color":"white" })
   4:         .click(function () { alert("hi"); });
   5: });

4. Add the following to your style sheet to style up the test div.

   1: .test{width:200px;
   2:    float:left;background:silver;
   3:    color:White;border:1px solid White;
   4:    cursor:pointer;padding:5px}

5. Open the page in a browser, then hover over the test div. If all goes well, you should see the following.

 

1447.image_12F3BB96

5287.image_2A3EC007

Obviously this isn’t the world’s greatest plugin, but does cover the basics of getting started. Information on building more functional plugins can be found at http://docs.jquery.com/Plugins/Authoring

TableSorter, a more functional plugin

Since we are working with tabular data in this application, I want to use a plugin that will modify an HTML table and make it sortable. Searching through the plugins library I found “TableSorter” at http://tablesorter.com. It is written by Christian Bach at www.lovepeacenukes.com and does a great job of providing a pretty nifty data grid from a static HTML Table.

Let’s take a look.

2744.image_3AD6BAF5

In the head tag of the HTML file place a reference to the TableSorter plugin right after the reference to the jQuery file.

2474.image_05114FCE

In the View in which you want to show the table, write your code to render a table with the data you want to show. One thing about the TableSorter plugin is that it requires valid HTML tables complete with <thead> and <tbody> tags. The following markup is written with the new MVC 3 Razor View Engine.

   1: <table id="studentTable" class="studentTable {sortlist: [[6,0]]}">
   2:     // sortlist is a function of the plugin which automatically sorts
   3:     // on a specific column
   4:     <thead>
   5:     <tr>            
   6:         <th>First Name</th>
   7:         <th>Last Name</th>
   8:         <th>Email</th>
   9:         <th class="{sorter: false}">Comments</th> 
  10:         // sorter class is a plugin option
  11:         <th>Submit Date</th>
  12:         <th>Approved Date</th>
  13:         <th>Approved</th>
  14:     </tr>
  15:     </thead>
  16:     <tbody>    
  17:     @foreach (var item in Model)
  18:     {        
  19:         var approvedDate = string.Empty;
  20:         if (item.ApprovedDate.HasValue) { 
  21:             approvedDate = item.ApprovedDate.Value.ToShortDateString(); 
  22:         }
  23:           <tr>               
  24:             <td>@item.FirstName</td>
  25:             <td>@item.LastName</td>
  26:             <td>@item.Email</td>
  27:             <td>@item.Comments</td>
  28:             <td>@item.SubmitDate.ToShortDateString()</td>
  29:             <td>@approvedDate</td>
  30:             <td>
  31:               <span style="display:none" class="hiddenSpan">@item.Approved</span>
  32:               @Html.Hidden("Approved", item.Approved)
  33:               @Html.Hidden("studentId", item.Id)
  34:               @{var chk = "chkGraphic chkUnChecked";}
  35:               @if (item.Approved.HasValue && item.Approved.Value.Equals(true))
  36:               {
  37:                   chk = "chkGraphic chkChecked";
  38:               }
  39:               <div class="@chk"></div>
  40:               <img src="../../Content/Images/ajax-loader.gif" 
  41:               class="ajaxLoader ajaxLoaderSmall" />
  42:             </td>
  43:         </tr>
  44:     }    
  45:     </tbody>
  46: </table>

Since we are rendering a table, we can use the $(document).ready(function(){});

Add the following in your custom JavaScript file:

   1: /// <reference path = "/Scripts/jquery-1.4.1-vsdoc.js"/>
   2:  
   3: $(document).ready(function () {
   4:     $("#studentTable").tablesorter({ widgets: ['zebra'] });
   5:     // zebra is a “widget” included in the plugin which will alternate
   6:     // the row colors of the table
   7: });

Run the page and sort the columns. One thing to note in the markup is in the last column. The plugin sorts on the data contained in the columns of each row. Since I want to sort on “Approved”, I add a hidden field with that data as the first element in the cell.

7024.image_5BBA07CF

2133.image_5713D748

The TableSorter plugin has many more options than this brief demo show. If you want to explore it more, download it at http://tablesorter.com.

A Freebie

If you look at lines 30 - 42 in the markup you may be wondering what all the other stuff is, including the <div class=”@chk”></div>. I wanted to spiff up the form and use graphics for the checkboxes, but still keep the functionality of a checkbox. Here is how to do it.

1. In the style sheet add the following classes.

   1: .chkGraphic{cursor:pointer;width:22px;height:22px;float:left;margin-right:5px}
   2: .chkChecked{background:url(Images/checkBoxOn.png)no-repeat}
   3: .chkUnChecked{background:url(Images/checkBoxOff.png)no-repeat}

2. In your custom JavaScript file, add the following functions.

   1: $("div.chkGraphic").live("click", function () { toggleGraphicCheckBox(this); });
   2:  
   3: function toggleGraphicCheckBox(elem) {
   4:     var $elem = $(elem);
   5:     $elem.siblings("img.ajaxLoader").show();
   6:     var valueField = $elem.siblings("input[type=hidden][name=Approved]");
   7:     if ($elem.hasClass("chkChecked")) {
   8:         $elem.removeClass("chkChecked").addClass("chkUnChecked");
   9:         valueField.val("False");
  10:     } else {
  11:         $elem.removeClass("chkUnChecked").addClass("chkChecked");
  12:         valueField.val("True");
  13:     }
  14:     $("span.hiddenSpan").html(valueField.val());
  15:     toggleStudentApproval($elem);
  16: }
  17:  
  18: function toggleStudentApproval(elem) {    
  19:     var approved = elem.siblings("input[type=hidden][name=Approved]").val();
  20:     var studentId = elem.siblings("input[type=hidden][name=studentId]").val();
  21:     $.ajax({
  22:         url: "/Home/GetStudent/" + studentId + "/" + approved,
  23:         type: "GET",
  24:         success: function (result) {
  25:             showStudentApproval(result, elem);
  26:         }
  27:     });
  28: }
  29:  
  30: function showStudentApproval(result, elem) {    
  31:     var id = result.Id;
  32:     var td = elem.parent("td").prev("td");
  33:     td.html("");
  34:     if (result.ApprovedDate != null)
  35:         td.html(result.ApprovedDate);
  36:     elem.siblings("img.ajaxLoader").fadeOut(500);
  37: }

Here’s the markup again.

   30: <td>
   32:  <span style="display:none" class="hiddenSpan">@item.Approved</span>
   33:  @Html.Hidden("Approved", item.Approved)
   34:  @Html.Hidden("studentId", item.Id)
   35:  @{var chk = "chkGraphic chkUnChecked";}
   36:  @if (item.Approved.HasValue && item.Approved.Value.Equals(true))
   37:  {
   38:     chk = "chkGraphic chkChecked";
   39:  }
  40:  <div class="@chk"></div>
  41:  <img src="../../Content/Images/ajax-loader.gif" 
  42:        class="ajaxLoader ajaxLoaderSmall" />
  43: </td>

Now based on what you’ve read so far in this and the previous articles, take a look at all the code and see if you can figure out what will happen when the graphical checkbox is clicked. Add a comment to this article and let me know what you think it will do.

Just for grins and giggles, I converted the JavaScript above to a plugin, jquery.graphicCheckBox.js

   1: (function ($) {
   2:     $.fn.graphicCheckBox = function (options) {
   3:     var methods = {
   4:         // initialize stuff
   5:         init: function (options) { },
   6:         //destroy and clean up
   7:         destroy: function () {
   8:             return this.each(function () {
   9:                 $(window).undbind("graphicCheckBox");
  10:             })
  11:         }
  12:     };
  13:     // default settings if they aren't passed in
  14:     var settings = {
  15:         'checked': 'chkChecked',
  16:         'unchecked': 'chkUnChecked',
  17:         'urlToAction': '/Home/GetStudent/'
  18:     };
  19:         // add the settings into the options
  20:     return this.each(function () {
  21:         if (options) {
  22:             $.extend(settings, options);
  23:         }
  24:  
  25:         var $this = $(this);
  26:         $this.click(function (event) {
  27:             $this.siblings("img.ajaxLoader").show();
  28:             var valueField = $this.siblings("input[type=hidden][name=Approved]");
  29:             if ($this.hasClass(settings.checked)) {
  30:                 $this.removeClass(settings.checked).addClass(settings.unchecked);
  31:                 valueField.val("False");
  32:             } else {
  33:                 $this.removeClass(settings.unchecked).addClass(settings.checked);
  34:                 valueField.val("True");
  35:             }
  36:             $("span.hiddenSpan").html(valueField.val());
  37:             toggleApproval($this);
  38:         });
  39:     });
  40:     function toggleApproval(elem) {
  41:         var approved = elem.siblings("input[type=hidden][name=Approved]").val();
  42:         var id = elem.siblings("input[type=hidden][name=studentId]").val();
  43:         $.ajax({
  44:             url: settings.urlToAction + id + "/" + approved,
  45:             type: "GET",
  46:             success: function (result) {
  47:                 showApproval(result, elem);
  48:             }
  49:         });
  50:     }
  51:     function showApproval (result, elem) {
  52:         var id = result.Id;
  53:         var hid = elem.siblings("input[type=hidden][name=studentId]").val();
  54:         var td = elem.parent("td").prev("td");
  55:         td.html("");
  56:         if (result.ApprovedDate != null)
  57:             td.html(result.ApprovedDate);
  58:         elem.siblings("img.ajaxLoader").fadeOut(500);
  59:     }
  60: }
  61: })(jQuery);

In this article we talked about extending jQuery with plugins, how to write a simple plugin, and explored a fully functional table sorter plugin. I even threw in a groovy freebie for you.

Happy Programming,

James

jQuery and MVC Part 2

By James at November 15, 2010 17:46
Filed Under: JavaScript, MVC, jQuery

In our last episode we went over the basics of JavaScript and the jQuery library. In this installment I will show you the basics of MVC and how it renders HTML differently than Web Forms pages, and finish up showing some basic Ajax with jQuery.

When ASP.NET first arrived it was a good thing. Web Forms allowed developers to build websites in a way that was very similar to how Windows Forms applications where built, with drag and drop of controls and a “code behind” architecture. Web Forms served their purpose for many, many applications in the enterprise, and many commercial applications, both large and small were successfully built using this technology.

When “Web 2.0” arrived, complete with Ajaxy interactions, Microsoft put forth their own brand of controls to handle this, and for the most part this worked, and continues to work well. However the Web Forms framework makes it difficult to build clean, lean web sites, as the technology depends on many different things in the rendered HTML to make it usable when posting back to the server. Two of the main items are ViewState and Control Rendering.

ViewState is sent to the browser as a way to capture what is on the page, and what has been changed when the request is sent back to the browser. For ViewState to work, controls on the page need to be rendered with specifically named ID’s. This makes it difficult to use JavaScript to find elements on the page by their ID. For example adding a button to a page that is using an ASP.NET Master Page will render the following HTML:

Source code:

   1: <asp:Panel ID="Panel1" runat="server">
   2:     <asp:Button ID="btnClick" runat="server" Text="Button" />
   3: </asp:Panel>

Rendered HTML:

   1: <div id="MainContent_Panel1">    
   2:    <input type="submit" name="ctl00$MainContent$btnClick" 
   3:       value="Button" id="MainContent_btnClick" />    
   4: </div>

ViewState:

   1: <div class="aspNetHidden">
   2: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
   3:    value="/wEPDwUJNjE3ODYxMzIwZGQjyMGaAJ/BFAzxJv1b+/lEXPaj4I/hCsdqNKZUozZiyw==" />
   4: </div>

If you notice you will see both the name and the id of the button has been changed to show that it is a child of the asp:Panel which is a child of the ASP.NET MasterPage. The ViewState in this example is fairly lean, but in large pages, it can become very large, and this is data the browser needs to download.

While this is all fine and dandy, trying to access these elements can be difficult, especially when trying to use jQuery’s selector mechanisims. You may think, that if you keep the name the same when traversing the DOM, will keep it good. But if for some reason the ID of the parent element changes in your code, then the names will change. There are some tricks you can use, but they are not the basis of this tutorial.

Now, let’s look at the same page when rendered with MVC:

Source code:

   1: <asp:Panel ID="Panel1" runat="server">
   2:     <input type="submit" value="button" />
   3: </asp:Panel>

Rendered HTML:

   1: <div id="MainContent_Panel1">    
   2:    <input type="submit" value="button" />    
   3: </div>

Now keep in mind that ASP.NET MVC does not typically use ASP.NET controls and in this example I am using a standard HTML input tag for the submit button.

The ASP.NET MVC Framework – What is it?

Now before we get into a big discussion about what is better and what is not, and all the underpinnings of “who moved my cheese”, MVC is yet another way to build web sites using the .NET Framework. It is a web application framework which implements the model-view-controller pattern of development. It is based on ASP.NET and allows the development of a web application to be built using three roles; Models – the data coming into and out the application, Views – the displayed pages, and Controllers – which handle the traffic coming in for HttpRequest and HttpResponse.

Microsoft released a CTP version of MVC in December, 2007, MVC version 1 in March 2009 and MVC version 2 in March 2010. They are currently working on version 3.

The default View engine for MVC is the Web Forms view engine and this view engine uses regular .aspx pages to design the layout of the user interaction pieces of the web site or web application. Instead of PostBacks any interactions are routed to the Controllers using a Routing mechanism.

A typical ASP.NET MVC application will have the following directory structure as seen in this figure:

3036.MVC-Folder-Structure_741D04C1

As you can see there are folders for Controllers, Models, and Views. Look closely and you will see that the Controllers names are associated with the folders in the Views folder. AccountController maps to Views\Account while HomeController maps to Views\Home. Views that are shared throughout the application are saved in the Views\Shared folder.

Let’s take a look.

4621.Student-Course-Admin_3568075B

The first part of the application allows the user to look up a student by ID. As we can see from this screen shot the student with an ID of 1 is Jeanine Abbott. There are many steps involved in doing this using HTML, CSS and jQuery, so let’s dive in.

Index.aspx has the following code:

   1: <div class="row">
   2:     Find student by ID
   3:     <input type="text" id="studentId" value=""  class="studentId" />
   4:     <input type="button" id="btnAjax" value="Get Student" />
   5:     <img src="../../Content/Images/ajax-loader.gif" class="ajaxLoader" 
   6:          alt="ajaxloader" />
   7: </div>
   8: <div class="row">
   9:    <div class="errorMessage"></div>
  10:    <div class="studentData">
  11:     <table>
  12:         <thead>
  13:         <tr>
  14:             <th>First Name</th>
  15:             <th>Last Name</th>
  16:             <th>Email</th>
  17:             <th>Submit Date</th>
  18:             <th>Approved</th>
  19:             <th>Approved Date</th>
  20:         </tr>
  21:     </thead>
  22:     <tbody>
  23:         <tr>
  24:             <td class="studentFirstName"></td>
  25:             <td class="studentLastName"></td>
  26:             <td class="studentEmail"></td>
  27:             <td class="studentSubmitDate"></td>
  28:             <td class="studentApproved"></td>
  29:             <td class="studentApprovedDate"></td>
  30:         </tr>
  31:     </tbody>
  32:     </table>
  33:   </div>
  34: </div>

The next piece is in the HomeController where we have a method called GetStudent(int id)

   1: private readonly CourseEntities _db = ModelHelper.CourseEntities;
   2: public JsonResult GetStudent(int id)
   3: {
   4:     var student = (from s in _db.Students
   5:                    where s.Id.Equals(id)
   6:                    select s).FirstOrDefault();
   7:  
   8:     if (student == null) 
   9:         return Json("error:Student not found.", JsonRequestBehavior.AllowGet);
  10:  
  11:     var singleStudent = new SingleStudent
  12:         {
  13:             Id = student.Id,
  14:             FirstName = student.FirstName,
  15:             LastName = student.LastName,
  16:             Email = student.Email,
  17:             SubmitDate = student.SubmitDate.ToShortDateString(),
  18:             Approved = student.Approved.ToString(),
  19:             ApprovedDate = string.Empty
  20:         };
  21:  
  22:     if(student.ApprovedDate.HasValue)
  23:         singleStudent.ApprovedDate = student.ApprovedDate.Value.ToShortDateString();
  24:     
  25:     return Json(singleStudent, JsonRequestBehavior.AllowGet);
  26: }

The third piece of the puzzle is in the CSS. Looking at the ASPX code there are two div elements with classes of “studentData ” and “errorMessage”. In the CSS for this project these two classes have been defined as:

   1: div.studentData{display:none}
   2: div.errorMessage{display:none;color:Red;font-weight:bold;}

This makes these elements, and any elements contained within them to not be displayed when the page is first rendered.

The last piece to come into play is the JavaScript and jQuery. It is important to know that when adding your script references to your page, to make sure they are in the correct order. When you are going to use jQuery in your application and additional JavaScript files, the reference to jQuery needs to be first.

   1: <head id="Head1" runat="server">
   2:     <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
   3:     <script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script>
   4:     <script src="../../Scripts/AppScripts.js" type="text/javascript"></script>
   5: </head>

I have written an additional JavaScript file, “AppScripts.js” and included it in the Scripts folder of the application. And by adding a reference to “jquery-1.4.1-vsdoc.js” to your additional JavaScript files, Visual Studio will provide jQuery Intellisense to make it easier reference the jQuery functions and attributes.

   1: /// <reference path = "/Scripts/jquery-1.4.1-vsdoc.js"/>
   2:  
   3: $(document).ready(function () {
   4:     $("#btnAjax").click(function () { getStudent(); });    
   5: });

Going back to the first article in this series, you can see that when the document has been fully loaded into the DOM, with $(document).ready(), the element with the ID of “btnAjax” will have a click event assigned to it. The JavaScript function getStudent() is below.

   1: function getStudent(id) {
   2:     $("img.ajaxLoader").fadeIn(500);
   3:     $("div.errorMessage").fadeOut(500);
   4:     $("div.studentData").fadeOut(500);
   5:     $.ajax({
   6:         url: "/Home/GetStudent/" + $("#studentId").val(),        
   7:         type: "GET",
   8:         success: function (result) {
   9:             if (typeof (result) == "string" && result.indexOf("error:") > -1) {
  10:                 showError(result);
  11:             } else {
  12:                 showStudentData(result);
  13:             }
  14:         }
  15:     });
  16: }

Let’s step through this. Line 1 hides the ajaxLoader image, lines 2 and 3 hide the errorMessage and studentData div tags. Line 4 starts the jQuery ajax function by defining the url, the form action type, and what to do on a successful response. Because I am using a “GET” in the ajax code, I don’t have to include a <form> on the page. Looking back to the GetStudent(int id) method in the Controller, it is expecting a parameter of the type int to be passed in as well. This is done by getting the value of the text field which has an ID of “studentId”;

How the routing is setup with the application, the MVC framework will automatically cast the “1” to an int before it is passed into the method.

The GetStudent () method will take the ID passed in then select the student with a matching ID. If no student is found, GetStudent() will return a string, “error:Student not found.” If a student is found, then the method will return a Json object containing the data of the student.

Using Firebug for Firefox is a good way to see the data which is coming back from the Controller.

When an error is returned, in this case, the student was not found

3036.GetStudent-with-Error_33D6C57A

6557.GetStudent-with-Error-web-page_44028D73

When a student object is returned

5086.GetStudent-with-student_1B83AB5F

5873.GetStudent-with-student-web-page_604FCF93

The success attribute of the $.ajax function will check the type of the result coming back. If it is a string, the showError() function is called. If the type of the result coming back is an object, we know it is a JSON object and the showStudentData() function is called which will display the student’s data.

   1: function showError(result) {
   2:     var msg = result.split(":");
   3:     $("div.errorMessage").html(msg[1]).fadeIn(500);
   4:     $("img.ajaxLoader").fadeOut(500);
   5: }
   6:  
   7: function showStudentData(student) {
   8:     $("td.studentFirstName").html(student.FirstName);
   9:     $("td.studentLastName").html(student.LastName);
  10:     $("td.studentEmail").html(student.Email);
  11:     $("td.studentSubmitDate").html(student.SubmitDate);
  12:     $("td.studentApproved").html(student.Approved.toLowerCase());
  13:     $("td.studentApprovedDate").html(student.ApprovedDate);
  14:     $("div.studentData").fadeIn(500);
  15:     $("img.ajaxLoader").fadeOut(500);
  16: }

Another example

In this project, I want to quickly approve a student for the current course. I could build an Edit Student form and approve them with that, but I don’t want to handle all of that overhead. All I want to do is click the Approved checkbox and go onto the next student.

I can do this by adding a click event to the checkboxes that have been rendered on the page with the following line of jQuery code.

   1: $("input[type=checkbox][name=Approved]").live("click", function () {
   2:     toggleStudentApproval($(this)); 
   3: });

Notice how I am using the “live” event to bind the click event to the checkboxes. What is cool about doing it this way is, the event will be bound to all selected elements now and in the future. So if the page is heavy with elements and long in loading, the $(document).ready() function may fire before all the elements have been rendered. You may also create new DOM elements with jQuery which won’t be available during $(document).ready(), so setting events with the .live() event is a good practice to start.

The JavaScript code:

   1: function toggleStudentApproval(elem) {
   2:     $(elem).siblings("img.ajaxLoader").fadeIn(500);
   3:     var approved = $(elem).attr("checked");
   4:     var studentId = $(elem).prev("input[type=hidden]").val();
   5:     $.ajax({
   6:         url: "/Home/SetStudentApproval/" + approved + "/" + studentId,
   7:         type: "GET",
   8:         success: function (result) {
   9:             showStudentApproval(result);            
  10:         }
  11:     });
  12: }

When the checkbox is clicked the code first shows the animated GIF, “ajaxLoader” that is a sibling of the checkbox. It then sets the variable “approved” to the “checked” attribute of the checkbox, then gets the value of the hidden field “studentId”. Line 6 shows the url which will be sent to the Controller, and line 9 shows the function to be called when the response is received. The request is then sent to the SetStudentApproval method in the Home Controller.

The Controller method, SetStudentApproval

   1: public JsonResult SetStudentApproval(bool approved, int id)
   2: {
   3:     var student = (from s in _db.Students
   4:                     where s.Id.Equals(id)
   5:                     select s).FirstOrDefault();
   6:  
   7:     if (student == null)
   8:         return Json("error:Student not found.", JsonRequestBehavior.AllowGet);
   9:  
  10:     student.Approved = approved;
  11:     student.ApprovedDate = DateTime.Now;
  12:     if (!approved)
  13:         student.ApprovedDate = null;
  14:     _db.SaveChanges();
  15:  
  16:     var singleStudent = new SingleStudent
  17:     {
  18:         Id = student.Id,
  19:         FirstName = student.FirstName,
  20:         LastName = student.LastName,
  21:         Email = student.Email,
  22:         SubmitDate = student.SubmitDate.ToShortDateString(),
  23:         Approved = student.Approved.ToString()
  24:     };
  25:  
  26:     if (student.ApprovedDate.HasValue)
  27:         singleStudent.ApprovedDate = student.ApprovedDate.Value.ToShortDateString();
  28:     
  29:     return Json(singleStudent, JsonRequestBehavior.AllowGet);
  30: }

This method is the similar to the GetStudent method earlier in the article. For ease in reading, I copied it and added passing in the “approved” status, then passing back the student object to the JavaScript function.

The additional JavaScript functions

   1: function showStudentApproval(result) {
   2:     var id = result.Id;
   3:     var hid = getHiddenField(id);
   4:     var td = hid.parent("td").prev("td");
   5:     td.html("");
   6:     if (result.ApprovedDate != null)
   7:         td.html(result.ApprovedDate);
   8:     hid.siblings("img.ajaxLoader").fadeOut(500);
   9: }
  10:  
  11: function getHiddenField(id) {
  12:     var hid;
  13:     $("input[type=hidden]").each(function () {
  14:         if ($(this).val() == id) {
  15:             hid = $(this);
  16:             return false;
  17:         }
  18:     });
  19:     return hid;
  20: }

The function showStudentApproval gets the Id of the student, then calls a helper function, getHiddenField to find the matching hidden field. This is so the table cell displaying the Approved Date can be found. The helper function gets an array of all hidden fields in the DOM, and uses the jQuery function .each() to loop through each one checking the value to see if it matches what was passed in. When it finds the correct element, the variable “hid” is set to the hidden field, then the looping is stopped. The hidden field is then sent back to the showStudentApproval function.

For ease, and since only the checkbox is visible, the hidden field, the checkbox and the animated GIF are all in the same table cell. Line 4 finds the table cell which is to the left of the cell holding these elements by traversing the DOM, looking first for the parent(), then parents previous sibling.

8688_nested-table-cell_0500E70B

Line 5 shows that once you have a jQuery object in memory, you don’t have to use the $() syntax to refer to it again. This is a best practice, as using the $() to find elements which you already have in memory will lead to a degradation in performance.

Line 5 clears out the html of the table cell we found by traversing the DOM in line 4. Lines 6 and 7 set the html of the table cell to the student’s ApprovedDate.

Step 1

2287.student-approval-1_63350E79

Step 2

4405.student-approval-2_61F0759A

Step 3

3718.student-approval-3_4BBA5A48

In this article we talked about some of the differences between a Web Forms application and a MVC application. Showed how to include jQuery files, and did some cool things with Ajax and jQuery to streamline an application’s functionality. In the next article, I will show you how to extend jQuery’s functionality with plugins.

Happy Programming,

James

JavaScript delete confirmation with the C1 ASP.NET GridView

By James at November 08, 2010 23:04
Filed Under: JavaScript, C1GridView, ASP.NET

The ComponentOne ASP.NET GridView allows you to add a Delete button to remove a record from the DataTable. However there isn’t a native way to add a confirmation that you really want the record deleted. It’s always best to check for sure when it comes to destructive actions, so I did some spelunking and came up with a way to do it.

1. Add a Template Field column to the grid by using either the property builder, or in the declarative code of your .aspx page.


7587.blog1b_68AFA015

2. Go into source view and add an ItemTemplate, then an asp:ImageButton.

     <cc1:C1TemplateField>
          <ItemStyle Width="25px" VerticalAlign="Top" />
          <ItemTemplate>
               <asp:ImageButton ID="lbDelete" 
                  runat="server" 
                  ImageUrl="~/Images/delete.gif" />
           </ItemTemplate>
      </cc1:C1TemplateField>

3. In the main C1GridView declaration add a method for the OnRowDataBound event. In this case I added the following:

        OnRowDataBound="AddJavaScriptConfirm" 

4. Add your method to the code behind:

   protected void AddJavaScriptConfirm(object sender, C1GridViewRowEventArgs e)
    {
        C1GridViewRow row = e.Row;
        ImageButton imageButton = (ImageButton) row.FindControl("lbDelete");
        if(imageButton != null)
        {
          imageButton.Attributes.Add("onclick", 
          "java-script:return confirm('Are you sure you want to delete this record?')" );
        }
    }

What this does is for every row that is databound it finds the ImageButton with the ID of “imgDelete” then adds the “onclick” attribute to the element when it is rendered as html

     <td class="C1Gtd" valign="top" style="width:25px;">
          <input type="image" name="ctl00$MainContent$C1GridView1$ctl01$ctl07$lbDelete" 
             id="MainContent_C1GridView1_lbDelete_4" src="Images/delete.gif" 
             onclick="java-script:return confirm(&#39;Are you sure you want to 
               delete this record?&#39;);" />
     </td>
 

NOTE: I had to change javascript to java-script as this blog system sees it as a potential threat. If you copy this code, change the java-script back to javascript.

2260.blog1a_57E7F567

6761.blog2a_2E90AD69

That’s it. Easy, peasy, nice and cheesy.

Happy programming,

James

jQuery and MVC–Part 1

By at October 27, 2010 07:27
Filed Under: JavaScript, MVC, jQuery

This is the first in a four-part series on using the JavaScript library jQuery with the ASP.NET MVC framework.

Introduction

In the beginning there was static HTML and it was good. The World Wide Web was in its infancy and anyone with a computer, a text editor, an FTP program and a connection to the internet – more than likely dial-up – could create and publish web pages. But quickly these pages became boring, as they were after all, static, and web publishers began clamoring for something to make their pages zing.

Then along came a scripting language called JavaScript, and changed the way web pages and sites looked and acted, creating new ways to provide interactivity between the user and the web server. It was first released by Netscape as LiveScript in September 1995, and was renamed to JavaScript in December 1995 when it was included in the release of the Netscape browser.

As a programming language it is dynamic, weakly typed, prototype-based and supports closures and higher order functions. Not to be confused with the Java language it does have some similarities in its syntax with curly braces “{}” and semi-colons “;” and copies many names and naming conventions. However like Java, it does have a fairly steep learning curve. Because of this, JavaScript “scripts” started to become more and more popular on web development sites, allowing for easy copy and pasting. While this made JavaScript to quickly become one of the most popular languages for web development, in some circles it gained the reputation of being a “kiddie” language.

In 1999, Microsoft released the IXMLHTTPRequest interface as part of their Outlook Web Access for Microsoft Exchange Server. The Mozilla Foundation developed a wrapper to use this interface through a JavaScript object which was called XMLHttpRequest. In April, 2006 the World Wide Web Consortium published a working draft to “document a minimum set of interoperable features based on existing implementations, allowing Web developers to use these features without platform specific code”. The last revision to the specification was in November, 2009. (http://en.wikipedia.org/wiki/Xmlhttp)

With the advent of Ajax (Asynchronous JavaScript and XML) in 2005, JavaScript had begun to be looked on more favorably by the programming community, and as a more full-featured language.

The Pros and Cons

As with all languages there are many pros and cons, likes and dislikes, friends and foes. JavaScript is no different and some of the most common are:

Pros Cons
Dynamic
Easy to develop with and debug with the appropriate tools
Similar, comfortable syntax to Java, C#, C
Browsers seem to have their own JavaScript engine
Can be difficult to have the same behaviors act the same across browsers

The Development Experience

You get into the learning curve, and spend all your waking hours writing the most unique and elegant piece of JavaScript code, and test it in your favorite browser. It works just how you planned, until you open your site in a different browser. Ugh, events are different, you can’t seem to get to the correct DOM element, nothing just seems to work between browsers, let alone platforms. You pour over your trusty JavaScript manuals, scour forums, Google on Bing for obscure error messages, and generally get frustrated. You just feel like giving up, so what do you do?

JavaScript Libraries to the rescue

JavaScript libraries are pre-written snippets of code and controls which usually form a much larger JavaScript Framework. These libraries allow for the easier development of JavaScript intensive applications, as the majority of them handle the problems of cross-browser, cross-platform issues. Numerous libraries are available including, but not limited to, Dojo, Echo, Ext, Google Web Toolkit, jQuery, MochiKit, MooTools, Prototype, qooxdoo, Rico, script.aculo.us, Spry, and Yahoo! UI Library.

While each library has it’s good and bad points, it’s pros and cons, the rest of this series will focus the jQuery library, found at www.jquery.com

jQuery

In January 2006 John Resig, released the first version of jQuery at BarCamp NYC, as a free, open source, dual-licensed (MIT and GNU) library. According to http://trends.builtwith.com, jQuery is the most popular JavaScript library; with 38.62% of web sites tested using some form of the code. Some of the main features of jQuery are:

  1. Its syntax makes it easier to navigate the DOM (Document Object Model)
  2. Easily handles and binds events to any DOM element
  3. Creates both simple and complex animations
  4. Has a complete suite of Ajax grooviness baked in
  5. Easy extensibility with plug-ins
  6. Unobtrusive
  7. Microsoft bundles jQuery with ASP.NET Web Applications and ASP.NET MVC

That’s right. Microsoft has jumped on the jQuery bandwagon, and gives it full support, even committing code back into source control. In fact, you can call Microsoft Support and get help with jQuery.

Syntax

The learning curve for getting up to speed with jQuery is not terribly steep. In only a short time you can easily grok the basics, and in a few hours, do some really nifty things with jQuery.

The jQuery syntax is easy to learn with all statements starting off with a “$”. One of the cool things about jQuery is since other libraries may use the $ as well, to prevent collisions, you can use the literal “jQuery” instead. For example:

$(“some element”); or jQuery(“some element”);

DOM elements are selected by either their ID, or a className that has been assigned to them.

$(“#myElement”); returns the only ID in the DOM, “myElement”
$(“div.myElement”); returns all div elements having a class assigned of “myElement”

jQuery makes it very easy to traverse through the children of each element as well.

$(“div.main ul li”); returns all li tags within the div tag with a class of “main”

Whereas

$(“div.main”).find(“li”); returns the same collection as above.

You can select specific elements in the collection with special selectors such as :odd, :even, :first, :last, :not(), etc.

$(“div.main”).find(“li:odd”);
     returns all odd (zero-based) li tags inside the div with a class of “main”

$(“div.main”).find(“li:even”);
     returns all even (zero-based) li tags inside the div with a class of “main”

$(“div.main”).find(“li:first”);
     returns the first li tag

$(“div.main”).find(“li:last”);
     returns the last li tag

$(“div.main”).find(“li:not(li.someDifferentClass)”);
     returns all li tags that don’t have the “someDifferentClass” assigned to them

Unobtrusive JavaScript

How many times have we added our own “BLOCKED SCRIPTonclick(doSomething();)” code directly in our elements. It makes it difficult to maintain and debug, and rails against the philosophy of separation of concerns. jQuery helps us to get away from this by using selectors and assigning events to the elements we have found.

Additionally, unless you have written some really terrible jQuery/JavaScript, if there is an error in your jQuery syntax, jQuery will fail gracefully. This means there won’t be any pesky little JavaScript error icons in your browser or JavaScript console.

Events

It is very easy to assign an event (click, focus, blur, etc.) to any DOM element with jQuery, and there are two main methods to do this.

The first is to wait until the DOM is fully loaded, which is checked by the jQuery event, .ready(). This event is fired when the DOM is complete and has been loaded into the memory of the browser.

$(document).ready(function() {
    $(“myElement”).click(function() { doSomething(); });
});

The second method is to attach a “live” event to the element with

$(“myElement”).live(“click”, function(){ doSomething(); });

The differences between these two methods are slight, but important. In the first example, we are assuming there will be an element called “myElement” in the DOM. This could be an element that is hard coded in the HTML, a button, text field, image, div or p tag. However, with jQuery’s dynamic DOM manipulation, it is possible that you would reference an element that has not been created yet.

The .live() event attaches the function you want to call to all matched elements in the selector, regardless of if they have or have not been created yet.

In the examples above, the “doSomething()” is referencing a separate JavaScript function. Another method is to replace the “doSomething()” with more jQuery functions.

$("ul.demo li:odd").each(function (index) {
     var targ = this;
     setTimeout(function () {
       $(targ).addClass("liSelected");
     }, index * 500);
   });
}

jQuery functions can have standard JavaScript functions in them as well. Can you look at the code above and figure out what this event will do?

First, all of the odd li elements in the ul element with a className of “demo” are selected. Second, the jQuery .each() function loops through the collection, setting a brief timer. Third when the timer is hit, the li element has the class of “liSelected” assigned to it.

jQuery’s silent error handling will not show any indication of something going wrong, just since the element hasn’t been created it won’t be able to have the click event attached to it.

Chaining

Once an element has been found, a reference to the element is kept in memory. So, instead of the following:

$(“div.myElement”).hide();
$(“div.myElement”).html(“howdy”);
$(“div.myElement”).addClass(“red”);
$(“div.myElement”).fadeIn(“slow”);

You can chain the actions like so:

$(“div.myElement”).hide().html(“howdy”).addClass(“red”).fadeIn(“slow”);

This makes for much cleaner or succinct code writing and will help with memory as well.

Stuff you can do

As this series progresses, we will dive deeper into all the jQuery goodness. Here is a sampling:

  • Selectors – find elements in the DOM
  • Attributes – get/set attributes of found elements
  • Traversing – moving up/down elements in the DOM
  • Manipulation – get/set contents of found elements
  • CSS – get/set style attributes of found elements
  • Events – fire on click, hover, load, etc. of found elements
  • Effects – fadeIn/Out, slideIn/Out, hide/show
  • Ajax – full and complete Ajax capabilities
  • Utilities – inArray, isArray, makeArray, etc.

Benefits

In closing the benefits of using jQuery are incredibly apparent. It is a solid, standardized JavaScript library, which allows for fast development, and gracefully fails with no glaring errors or frozen pages. Because of its popularity, there are lots and lots of examples, and it is very easy to get ramped up and understand its simplicity.

Check back next week when we will dive deeper into jQuery, and how you can easily spiff up your sites. Take a look at the attached demos, and send me some comments and questions.

James

Firestarter 2008 ADO.NET Data Services Slides and Code

By James at May 18, 2008 09:47
Filed Under: Web Development, Microsoft

Yesterday I gave my presentation on ADO.NET Data Services at the Firestarter SQL 2008 event at the Microsoft Training Center in Irvine. I had a great time presenting, they even had to move my group to a bigger room, and it more than made up for the stress of trying to prepare a presentation with fluidly changing bits.

For your pre-beta, pre-CTP enjoyment I give you my slides and code firestarter-adodataservices.zip (588.30 kb)

If you have questions, drop me a line,

James 

Streamlining my Javascript some more...

By James at November 14, 2007 06:23
Filed Under: Web Development, Ajax and Javascript
I've been working on updating the MyUCR project at work. I'm always amazed at how much I learn, looking at my code from a year ago gives me shudders, compared to what I know now. For instance, here's a snippet of an Ajax call from last year:
var url = "ajax.aspx?getSingleMsg="+msgID + "&msgTypeID=" + getMessageType();
var xhrReq = xhrRequest("text");
xhrReq.open("GET", url, true);
xhrReq.onreadystatechange = function()
{
if(xhrReq.readyState == 4 && xhrReq.status == 200)
{
DisplaySingleMsg(xhrReq.responseText, getMessageType())
};
}
sendRequest(xhrReq);

 

Yikes! That's a heck of a lot of lines to write and maintain. I love using jQuery, but hadn't really gotten into its Ajax events. I wish I had done so earlier. Now the same code looks like this:

var url = "ajax.aspx?getSingleMsg="+msgID + "&msgTypeID=" + getMessageType();
$.get(url, function(xhr){DisplaySingleMsg(xhr, getMessageType());});

Sweet!

James

Latest crazy song in my head Les Boukakes - Bledi - L'Alawi

Looking for white elephants

By James at November 09, 2007 14:39
Filed Under:

I wanted to add the Live Messenger plugin to my BlogEngine.NET blog and could get it working when running either in Cassini or IIS 6/7. However when I posted the changed files to my hosting server, it wasn't working. I had previously built a custom template for BE, and had problems with custom Javascript being linked correctly. I ended up adding the JS links to the bottom of the master page with the following code:

<script type="text/javascript" src="<%=Request.ApplicationPath %>/themes/<%=BlogSettings.Instance.Theme%>/jquery.js"></script>

That worked fine and I was stumped why my new JS code wasn't working.

It was only until I did the most simplest of things, "View Source" did I see that the source of the javascript file was now

"//themes/duringlunch/jquery.js"

I don't know why this happened. I hadn't changed the source of BE. Perhaps it was a setting change on the hosting server, I don't know.

What I ended up doing was moving the javascript files to the "js" main folder of BE and now all is good.

BTW, if you want to IM me via Messenger, just click on the "Instant Message James" link in the sidebar, and you're good to go.

James

Streamlining the JSON Serialization

By James at November 01, 2007 03:26
Filed Under: Web Development, Ajax and Javascript

For a while now I have been using the Newtwonsoft.Json dll to generate my JSON objects. The documentation is pretty sparse and I had to do a lot of experimentation to figure out the best way to do it. I ended up with this base code.

myUCR_DepartmentsTableAdapters.MyUCR_DepartmentsTableAdapter deptTA = new myUCR_DepartmentsTableAdapters.MyUCR_DepartmentsTableAdapter();
myUCR_Departments.MyUCR_DepartmentsDataTable deptDT = new myUCR_Departments.MyUCR_DepartmentsDataTable();
deptTA.FillDepts(deptDT);
StringWriter sw = new StringWriter();
JsonWriter writer = new JsonWriter(sw);
writer.WriteStartArray();

foreach (myUCR_Departments.MyUCR_DepartmentsRow deptRow in deptDT)
{
   writer.WriteStartObject();
   writer.WritePropertyName("deptID"); writer.WriteValue(deptRow.deptID.ToString());
   writer.WritePropertyName("dept"); writer.WriteValue(deptRow.department.ToString().Trim());
   writer.WriteEndObject();           
}
writer.WriteEndArray();
writer.Flush();
Response.Write(sw.GetStringBuilder().ToString());

 As you can see, that's a lot of code to serialize a simple datatable.

I wanted to find an easier way, so started browsing around. Googling for "JSON DataTable Serialization", I came across this article "A DataTable Serializer for ASP.NET AJAX" at denydotnet.com. What he did was to extend the JavaScriptConverter found in System.Web.Script.Serialization to serialize a DataTable. I looked through his code and decided to implement it.

Now here's how I do my serialization:

        MyUCR_LoginTableAdapter ta = new MyUCR_LoginTableAdapter();
        DataTable dt = ta.GetByTesting();
        JavaScriptSerializer toJSON = new JavaScriptSerializer();
        toJSON.RegisterConverters(new JavaScriptConverter[]{new JavaScriptDataTableConverter()});
        Response.Write(toJSON.Serialize(dt));

And what rocks is the object names are mapped to the column names in the database.

Cool

James

 

A baby in the house

By James at October 15, 2007 17:06
Filed Under: Life in General

We have a baby!

Ok, well she's not ours per se, but she's our 1 year old niece, Camila. She'll be staying with us, along with her parents, till after the first of the year. Its gonna be great to have a little one around for the holidays.

J

Latest crazy song in my head Peter White - Promenade - Promenade

About the author

James James is a five time and current Microsoft MVP in Client App Development, a Telerik Insider, a past Director on the INETA North America Board, a husband and dad, and has been developing software since the early days of Laser Discs and HyperCard stacks. As the Founder and President of the Inland Empire .NET User's Group, he has fondly watched it grow from a twice-a-month, early Saturday morning group of five in 2003, to a robust and rambunctious gathering of all types and sizes of .NET developers.

James loves to dig deep into the latest cutting edge technologies - sometimes with spectacular disasters - and spread the word about the latest and greatest bits, getting people excited about developing web sites and applications on the .NET platform, and using the best tools for the job. He tries to blog as often as he can, but usually gets distracted by EF, LINQ, MVC, ASP, SQL, XML, and most other types of acronyms. To keep calm James plays a mean Djembe and tries to practice his violin. You can follow him on twitter at @latringo.

And as usual, the comments, suggestions, writings and rants are my own, and really shouldn't reflect the opinions of my employer. That is, unless it really does.

James Twitter Feed

Recent Comments

Comment RSS

Month List