Monthly Archives: June 2008

Inlay Process Pictoral – The Ottoman Tray

I’ve been getting a bunch of requests lately for a video on my decorative inlay process. This is definitely on our 2008 to-do list. But until then, I decided to resurrect an old WWA forum post from 2005. Enjoy.

The project is an ottoman tray. It will be a simple piece of 3/4 maple ply with a substantial solid padauk border. The inlay, is a simple interpretation of the sun. So here we go. It all starts with your design. Draw it out exactly how you want it to appear. It helps to have center-line and reference marks as they will make your life easier when it comes time to keep things aligned. Next, position your drawing over the substrate and tape one side in position. Now you can slide in a piece of carbon paper. Simply trace your design thereby transferring it to the substrate. For this design, the reference marks aren’t all that critical since I only need to transfer my design to the substrate once. But if you are doing a more complex design like one of my leaves, you will be re-tracing the design several times. Reference marks are then imperative.

If you havn’t already done so, you want to prepare your inlay stock at this point. I milled up few pieces of padauk for the large spikes and canarywood for the small spikes and the body of the sun. I like to aim for 1/16?-1/8? thickness for my stock. My drum sander belt is broken so these are a bit larger than I was shooting for. Since I have repeated geometric shapes, my next step was to make a template for each piece out of 1/4? ply. I simply used the carbon paper to trace the design onto the ply and cut it at the bandsaw.
Then I finessed the edges with sandpaper. If I were doing a leaf design, I would just trace my design directly to my inlay material and cut it out at the bandsaw or scroll saw. So now I use my templates to make my actual inlay pieces. I double-stick taped the template to my inlay stock, rough cut them on the bandsaw, then flush-trimmed them at the router table. These pieces are awefully small to rout, but with the proper precautions, it is possible. Any spots that send up the caution flags were touched up using sandpaper. Then I quickly cut the cararywood into a half circle using a quick rig at the bandsaw.

Now comes the fun part. This part of the process is exactly the same whether you are doing straight lines, geometric shapes, or complex designs. Start by double stick taping the piece to be inlayed into the substrate. Notice that the spikes are being done before the circle. This is because I want to circle to overlap the spikes. If I did it the other way, the continuity of the circle would be ruined. This concept is very important when creating the illusion of depth. The next few steps require a steady hand and patience. Lay off the coffee for a few hours. Or if you like a challenge, drink three cups before you start like I did. With an X-acto knife, carefully trace the outline of the inlay piece. Don’t rush this part. Start with a light touch just severing the top fibers. After a few passes you can increase the pressure and you will have a nice sharp outline.

Once the entire piece is outlined, carefully remove it with a putty knife. Now we need to make that outline a bit more visible. Simply grab your pencil and trace around the outline. Its ok to be sloppy. Then erase the line using strokes perpendicular to the outline. This will make sure the pencil residue gets loaded into the cut while cleaning the rest of the marks.

Now its time to do the routing. I generally use two bits. I hog out the material with a decent sized straight bit. Then I sneak up on the line with a 1/16? bit. Yes, its THAT small!!! Set the router to cut just a bit shy of the thickness of the inlay material, strap on your helmet, and pray for mercy. A critical tool in this process is the hands-free magnifier. With good lighting, they are worth their weight in gold. Which is probably about $20. Coincidentally that is how much they cost.

Now unfortunately, no picture can do this part justice. With the 1/16? bit, you really need to be careful when sneaking up to your line. I usually lock the router in the on position and put both hands on the base of the router. This gives me exceptional control. If you aren’t comfortable with this type of maneuver, then don’t do it. But I can’t think of any other way to get the control I need. A key point here is to watch the tearout of the router bit as you approach your line. The cool part is that as you sneak up to the line the little tearouts are clearly evident. But as soon as you kiss the line, the tearouts fly out leaving a nice clean line. That’s how you know you are there. Pre-cutting with the X-acto knife is what makes this possible.

Once the routing is complete, its time to test the fit. The piece will rarely drop right in. Usually the recess needs a bit of work. I use the X-acto knife and a chisel to hit the corner and clean up my edges. As a final touch, I sand a slight chamfer into the inlay piece. This ensures a nice tight wedged fit. Once all the pieces fit nicely, I glue them in place and clamp them down with some sort of caul. In this case, a piece of scrap ply does a fine job.

At this point, I took a lunch break. Turkey, swiss, on wheat. Light mayo. Yogurt (mixed berry). Back to the shop. Now we need to flush everything up. You can use a variety of tools for this. I like to use a block plane to remove the bulk, then I switch to a card scraper or a cabinet scraper. I finish up with a quick sanding. This is also a perfect time to hide any flaws or oopsies. Cyanoacrylate (CA) glue and a little dust from the offending inlay can give nearly undetectable repairs. A quick sanding at 150 and we are ready to add the circle part of the sun. The circle pretty much goes in like the other pieces. After hitting the circle with block plane and smoothing plane, I sanded the whole piece to 220.

As you can see, it is important to plan out the order in which you will apply the inlays. As mentioned before, I wanted to circle of the sun to be the “top-most” part of the image, so it goes on last. With my leaves, I will do one half of a leaf at a time. The leaf that is in the background is done first. The overlapping leaf is then done on top of the first leaf, giving the impression of depth.

And here is the final product with the sculpted padauk frame and several coats of lacquer.

Bob’s Bench – Completed Bench and Friendly Wager

Last Thursday I put the finishing touches on my new workbench, just in time for a
Friday-morning photo session. The plan was to shoot on location, and editor Christopher
Schwarz and I were discussing the plan. The one item not resolved was actually moving
the bench from our shop to another shop with a more photogenic parking lot. Chris
proposed moving the bench completely assembled, and I said “why don’t we just take
it apart and move the pieces? I think that will be easier.”



His response was, "that will take 45 minutes or an hour; it will be quicker to just
throw it in the truck." Never afraid to disagree with the boss, I said "It won't take
that long, this will come apart in 10 or 15 minutes, and we won't need more than two
people to carry the parts." We went back  and forth for a few minutes. "No you
can't," "Yes I can" led to "No way," "Absolutely."

I don’t remember which of us was the first to say, “Want to bet?,” but the introduction
of that phrase changed things from theoretical discussion to practical demonstration.
The stakes were settled, and the time set for the following morning. As news of the
contest spread through the office, it was mutually decided to record the proceedings
on film and video.


When I designed this bench, I kept the component parts few in number. The two top
slabs are held to the leg structure with four lag bolts coming up through the top
rails on each end. With those bolts removed, the tops were placed out of the way on
a rolling cart, and I went after the four lags that secure the lapped dovetails at
the end of the upper rails. With that task accomplished, I put down the wrench and
removed the boards that make up the lower shelf. Those pieces are half-lapped and
simply sit on cleats attached to the rails. When those were removed and stacked, I
grabbed the hammer.


I lifted the idea for the joints on the ends of the lower rails from an old drawing
of a Nicholson
bench
. There is a dovetail-shaped slot in each leg, and half a lapped dovetail
on the  end of each rail. The rails slide into the slots, drop into position
and a wedge is tapped in from the outer side of the leg to lock the joint together.
This is a surprisingly strong connection, and if the joints loosen over time all I
need to do is reach down and give the end of the wedge a rap with my hammer. Tapping
from the other direction removes the wedges, allowing the rails to move up and out.
One of the wedges escaped my grasp and went scooting across the shop floot, costing
me about 10 seconds of time to retrieve it.


Here’s a look at the joints coming apart, and the two leg assemblies and lower rails
were added to the pile. Elapsed time: 6 minutes, 30 seconds. Putting the bench back
together is nearly as fast. It went back together for the photo shoot, and apart again
for the return trip to the shop. At the moment it’s not assembled. Another challenge
has been issued, and we’ll soon gather in the shop, stop watches and digital cameras
at the ready, to see how fast an old man can move putting the bench back together.

Details on building and using the bench will be included in our October issue, which
will be on sale around the first of September. In the meantime, there will be more
about it here on the blog as I put it to use. I’ve enjoyed building this bench, and
I’m looking forward to using it.



– Bob Lang

Using jQuery Plugins with ASP.NET

The controls found in the AjaxControlToolkit fit perfectly into the ASP.NET programming model (as to be expected). You can configure the controls properties through the markup which in turn affects how the control’s display and behavior on the client. Many of the control’s properties support databinding so using the controls within a databound control like a ListView or a GridView is no big deal. Take for example the ProgressBar Toolkit control I blogged about (here and here). One of the places that I use this control is in a GridView’s TemplateField. Instead of displaying the percentage as a text value, I use the ProgressBar to display the percentage in a more visual manner. It looks something like this …

Live Demo | Download

image

With the Toolkit, setting this up is really simple. Just use a databinding expression to set the Value property of the ProgressBar control to the value of the PercentComplete property of the databound item. Done.

And if I start using and building jQuery plugins I am thinking there will be cases where I am going to miss how simple this is. So after learning about jQuery’s metadata plugin, I thought it would be interesting to see explore it a bit more to see if it could be used to enable some of the common scenarios. There are 2 things the metadata plugin has going for it that I think will help it fit into the ASP.NET programming model …

  • If a jQuery plugin supports the metadata plugin in, you can specify the plugin options on a per element basis by using some JSON within the elements class attribute to specify the option properties you would like to use. To me this really doesn’t feel too different than pointing a Toolkit control (using TargetControlID) at an existing web control.
  • It can all be done via markup – no need to emit any extra javascript

Creating the Plugin

Before I show how this can be done using the ListView, I thought I would show what the jQuery plugin looks like (granted it doesn’t have nearly as many features as the Toolkit version, but it still very useful for the data grid scenario). Here is how the plugin works …

  1. Coalesce the default options together with any options that are explicitly provided when the progressbar plugin is applied (Line #5)
  2. Inject the DIV elements that are used for styling the progress bar (Line #9)
  3. Check to see if the metedata plugin is available. If it is override any of the element specific options (Line 12)
  4. Finally, use find to locate the progress_indicator DIV whose background image is set to the progress image (this is applied via the stylesheet). Set the title attribute of this element and animate the width to the specified value. (Lines #16-#20)

Could it get any simpler?

(function($) {       $.fn.progressbar = function(options) {         // build main options before element iteration         var opts = $.extend({}, {value:0, tooltip:''}, options);           return this.each(function() {             //  add the progress DOM structure             $(this).html('
'); // if the metadata plug-in is installed, use it to build the options var o = $.metadata ? $.extend({}, opts, $(this).metadata()) : opts; // locate the DOM element that contains // the progress image $(this).find('.progress_indicator') // add the tooltip .attr('title', o.tooltip) // and animate the width .animate({width: o.value + '%'}, 'slow'); }); }; })(jQuery);

Using the jQuery progressbar Plugin with the ListView

Then, I can use databinding expressions to encode the tooltip and value options using the databinding expression. It isn’t as pretty, but it defiantly works. All of the magic happens in line #16. And if you set the control to runat server, you could populate this value from the codebehind as well.

              
<%# Eval("ID") %> <%# Eval("Name") %>

Applying the Plugin

And the only remaining bit of awkwardness is that the progressbar plugin needs to be applied twice. Once when the page first loads.

function pageLoad(sender, args){     if(!args.get_isPartialLoad()){          //  apply the          $('.progressBar').progressbar();     } }

And then again just after an UpdatePanel is refreshed (I apply it to the panels new contents) …

Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function(sender, args){     var updatedPanels = args.get_panelsUpdated();     if(updatedPanels && updatedPanels.length > 0){         for(var i = 0; i < updatedPanels.length; i++) {              $('.progressBar', updatedPanels[i]).progressbar();         }     }                     });

Footprint

And as promised, here is the JavaScript and CSS footprint for this example. I am using ASP.NET AJAX's ScriptManager and UpdatePanel controls - so those are the axd JavaScript references. The JavaScript for my plugin is ~1 KB unminified.

JavaScript: 113 KB

image

CSS: 2 KB

image

That's it. Enjoy!

PlacesBar Editor Customizes Windows Explorer [Featured Windows Download]


Windows only: Donationware application PlacesBar Editor customizes the default shortcut locations in the Windows and Microsoft Office Save As and Open dialog boxes to give you easy access to the folders you use most. We’ve seen applications like this before, like previously mentioned, similarly named PlacesBar Editor, but this application’s ability to set different default save locations for Microsoft Office and Windows as a whole is a great addition. PlacesBar Editor is donationware, Windows only.


glowbuttons – Writing My First jQuery Plugin

So I figure what better way to learn more about jQuery than to dig right in and create a plugin or two? At first I thought this sounded pretty intimidating, but after browsing through some of the existing jQuery plugins I figured it might be easy enough to try and ‘rearrange’ one of the Toolkit controls that I created. So that is what I did with my GlowButtonExtender control I created a few months back (and I plan on doing it with the ProgressBar one as well very soon). I kind of liked this because I thought creating the same UI widget using both the Toolkit and jQuery might give a little more insight into what the relative advantages are between the two frameworks.

In case you didn’t see my original post on creating the GlowButtonExtender control, here is how it works: When you mouse over the button, it glows as it comes into focus and of course when the mouse leaves the glow slowly fades away. These are just screen shots so you will have to check out the demo page to see it in action.

Live Demo (IE7, FF and Opera)* | Download

* IETester seems to be on the fritz – so I wasn’t able to test in IE6.

image imageimageimageimage

Footprint

Before I jump into the details, I just thought that I would mention that from now on, all of my posts (at least the ones that include a live demo) will include a section titled Footprint that has a brief discussion on the size of JavaScript and CSS resources my post is making use of. I really should have been doing this all along, but better late than never, right? So here it is for this post. I am using minified versions of jQuery and the metadata plugin (58 KB total combined) plus the color plugin (another 4 KB). And finally, the JavaScript for my glowbuttons plugin is a whopping 3 KB un-minified plus another 2 KB for the CSS.

JavaScript: Total 64 KB

image

CSS: Total 2 KB

image

Basic jQuery Plugin Template

So to get started creating my glowbutton plugin I first did some googling and came across a great resource that goes over some of the basics about creating jQuery plugins. I recommend reading (and understanding) the code samples. Below is the shell that I started with for my plugin. I would pay particular attention to the following …

  • There is a decent amount of plumbing that really needs to be included in your plugin to make sure it can play together nicely with other jQuery plugins as well as other JavaScript libraries
    • Notice the first and last lines. The plugin is wrapped in a self executing function that takes a single parameter ‘$’. And the last line of code invokes the function passing in the global jQuery object. If you follow this pattern you can safely use the $ shortcut to refer to the jQuery object without worrying about colliding with other bits of JavaScript code that might also be running on the client. If you don’t write your plugin using this technique I believe you should not be using the $ shortcut at all (or do at your own peril).
    • Line 5 I am creating the entry point to my glowbuttons plugin and adding it to the $.fn object
    • If you notice in line 5, my plugin accepts a single parameter called options. I am using lines 19 through 24 to define the options my plugin supports as well as the default values for each of the properties. Line 8 examines the options my plugin is provided along with the default option values and fills in any missing options with the defaults. If no options are supplied all of the default values will be used.
    • Line 10 is where we actually start doing something. Here we iterate over each of the elements in the wrapped set and do something with them. Two things are important here. The first is that I am returning this which is a reference to the wrapped set. This allows users to chain calls together creating the nice compact, fluent interface that jQuery is know for. And the second is that where I have the comment ‘do something with $(this)’ is where the actual plug-in logic goes. We will see that soon.
(function($) {   //  add our glowbuttons function.  it accepts   //  a single parameter that specifies any parameters   //  our plugin supports   $.fn.glowbuttons = function(options) {          // build main options before element iteration     var opts = $.extend({}, $.fn.glowbuttons.defaults, options);          return this.each(function() {           //  do something with $(this).         //  this is where all of the core plug in code belongs       });   };      // default options - these are used of none others are specified   $.fn.glowbuttons.defaults = {     from: '#016bbd', '#b1ddff',     className: 'blue',     speed: 1000   };   //  invoke the function we just created passing it //  the jQuery object })(jQuery);

Adding the GlowButton Plugin Logic

So after creating the template, I went back to my existing GlowButtonsExtender logic and started moving it over into my plugin. My existing plugin did basically 3 things

  • Injected 2 SPAN’s surrounding the button that I am using for styling (border and background)
  • Injected some browser-specific style workarounds
  • Setup 2 Toolkit animations for animating the background color as the mouse enters and leaves the button

And adding this logic into the plugin was really easy. Below I am just showing the part where I iterate over the wrapped set, but you can see that on line 4 I am wrapping the button in 2 spans using the wrap function. Then I navigate up to the immediate parent nodes and apply some browser hacks (I left them out of the code snippet here because they don’t add much value). And finally, I attach to the outer most SPAN’s hover events and run a simple color animation when the button is hovered over.

return this.each(function() {     var button = $(this);     //  inject the parent nodes                 button.wrap('');          //  ** do some browser specific style workarounds          button.parent().each(function(){          var innerWrapper = $(this);                  //  ** do some browser specific style workarounds                  innerWrapper.parent().each(function(){                      //  ** do some browser specific style workarounds                  })                     //  add a class to the outer most node - this helps with theming         .addClass(o.className)         //  finally attach to the hover events to run the animation         .hover(             function(){                 $(this).stop();                 $(this).animate({ backgroundColor: o.to }, o.speed);             },             function(){                 $(this).stop();                 $(this).animate({ backgroundColor: o.from }, o.speed);             }         );                          }); });

And now I can do things like this …

$(document).ready(function(){        $('.glow').glowbuttons(); }); 

… and all of the INPUTs on my page with the glow CSS class will start glowing.

Overriding Options with the Metadata Plugin

And you could stop there if you want and have a pretty useful plugin. But, you can make your plugin even more flexible by adding support for the Metadata plugin. The Metadata plugin allows you to override the option values on a per element basis. So in the code snippet immediately above this I am applying the default options to all of the glow elements on the page. But that isn’t always what you want – and that is where the Metadata plugin becomes useful. With this plugin users can override the default options by specifying option values using the class attribute as follows …

         





And now we can still fire the same logic on document ready, but now because we are specifying different parameter values on a per element basis, we end up rendering the following buttons.

image

And best of all, to support this all we have to do us update our plugin and add a single line of code. In the snippet below I updated the template to check first check the current element (i.e. $(this)) to see if it has any metadata properties defined. If it does we will honor these values. And if the metadata plugin isn’t available, we just fall back and use what ever options are available.

(function($) {   //  add our glowbuttons function.  it accepts   //  a single parameter that specifies any parameters   //  our plugin supports   $.fn.glowbuttons = function(options) {          // build main options before element iteration     var opts = $.extend({}, $.fn.glowbuttons.defaults, options);          return this.each(function() {         //  if the metadata plug-in is installed, use it to build the options         var o = $.metadata ? $.extend({}, opts, $(this).metadata()) : opts;                  //  ... plugin logic              });   };      // default options - these are used of none others are specified   $.fn.glowbuttons.defaults = {     from: '#016bbd',   '#b1ddff',     className: 'blue',     speed: 1000   };   //  invoke the function we just created passing it //  the jQuery object })(jQuery);

And finally, here is the complete source code for the plugin.

(function($) {   $.fn.glowbuttons = function(options) {     // build main options before element iteration     var opts = $.extend({}, $.fn.glowbuttons.defaults, options);          return this.each(function() {         var button = $(this);         //  if the metadata plug-in is installed, use it to build the options         var o = $.metadata ? $.extend({}, opts, button.metadata()) : opts;         //  inject the parent nodes                     button.wrap('');         //  ie display workaround         button.css('display', $.browser.msie ? 'inline-block' : 'block');                  button.parent().each(function(){              var innerWrapper = $(this);                          //  more browser specific workarounds                 innerWrapper.css('display', $.browser.msie ? 'inline-block' : 'block');              if($.browser.msie) {                 innerWrapper.css({ 'position':'relative', 'left':'-1px' });             }                          innerWrapper.parent().each(function(){                 var outerWrapper = $(this);                 outerWrapper.css('display', $.browser.mozilla ? '-moz-inline-box' : 'inline-block');                 outerWrapper.css('backgroundColor', o.from);                                  //  our glossy image is a transparent PNG so                 //  we have a special class that uses an image filter                 if($.browser.msie && $.browser.version < 7) {                     outerWrapper.addClass('ie6');                     }                                  })             //  add a class to the outer most node - this helps with theming             .addClass(o.className)             //  finally attach to the hover events to run the animation             .hover(                 function(){                     $(this).stop();                     $(this).animate({ backgroundColor: o.to }, o.speed);                 },                 function(){                     $(this).stop();                     $(this).animate({ backgroundColor: o.from }, o.speed);                 }            );                              });     });   };     $.fn.glowbuttons.defaults = {     from: '#016bbd',   '#b1ddff',     className: 'blue',     speed: 1000   };   })(jQuery);

What am I doing to learn more about jQuery?

So far I have found jQuery pretty easy to learn. But I have also only just started so I feel like I have a lot of catching up to do. Here is what I am doing to learn more about jQuery ...

  • Take Scott Hanselman's advice and become a better dev by reading more code. The existing jQuery plugins are pretty readable. I think once you get past the seemingly goofy JavaScript syntax for controlling scoping the rest is pretty straight forward. Browse the plugins and see how they work. I think you might be surprised at how simple they are (I know I was)
  • Subscribe to jQuery's discussion board over on Google Groups.
  • Pick up a JavaScript reference book

  • Check out learningjquery.com it has some great information. Plus I was over there today and stumbled onto a comment that Martin Fowler made (obviously I don't know that it was him for sure, but you never know).
  • Both Dave Ward and Rick Strahl blog fairly regularly on using jQuery with ASP.NET. So if you haven't yet, subscribe to their feeds. (here and here)

That;s it. Enjoy!

WOODSMITH: Routing a 30° Chamfer

Routing a 30° Chamfer

DrawingOn a recent project, I wanted to rout a 30° chamfer on the edge of a workpiece. But my chamfer bit (and almost all chamfer bits) will only cut a 45° bevel. With a little modification to my router base I was able to make the 45° chamfer bit work.

As you can see in Fig. 1, the solution to this problem was to replace the router base plate with a 15° wedge. This simply changes the cutting angle of the bit from 45° to 30°. The wedge should be wide enough and long enough to provide a stable base for the router (Fig. 1a). And it can be screwed to the router base plate using the existing mounting holes.

The only trick to routing the chamfer is to keep the wedge flat on the workpiece and parallel to the edge.

Good woodworking,

Ted Raife
Online Editor, Woodsmith

Use jQuery and ASP.NET AJAX to build a client side Repeater

There was some interesting discussion on Matt Berseth’s blog recently, regarding methods for building and displaying markup on the client side. Though I haven’t posted any examples here before, rendering markup on the client is a technique that I use often and recommend.

By sending only data to the client, you can profoundly reduce the size of what you send and see a substantial increase in performance. You also allow yourself the ability to easily add features like light-weight sorting and paging on the client. This can not only improve your users’ experience, but reduce server load and bandwidth requirements.

To that end, I’m going to walk you through these four steps to effectively implementing a client side Repeater, using ASP.NET AJAX and jQuery:

  • Create an RSS Reader page method to return JSON data to the client.
  • Call that page method with jQuery.
  • Use the returned data to build a table on the client side.
  • Improve upon the table creation with a templating plugin.

Creating an RSS reader page method

Because web browsers prohibit cross-domain AJAX functionality, displaying items from an external RSS feed is a good real-world example. To overcome this limitation, our first step is to write a local server side proxy to relay that feed data to the client.

A web service or page method is ideal for this task. I would typically use an ASMX web service, but let’s use a page method here. It’s useful to illustrate how nearly interchangeable the two really are.

[WebMethod] public static IEnumerable GetFeedburnerItems(int Count) {   XDocument feedXML =      XDocument.Load("http://feeds.encosia.com/Encosia");     var feeds =      from feed in feedXML.Descendants("item")     select new     {       Date = DateTime.Parse(feed.Element("pubDate").Value)                      .ToShortDateString(),       Title = feed.Element("title").Value,       Link = feed.Element("link").Value,       Description = feed.Element("description").Value     };     return feeds.Take(Count); }

This page method uses LINQ to parse a few details out of the RSS feed, create an anonymous type with that data, and then return a collection of those anonymous types. By selecting only the data we’re interested in on the server side, we can minimize the traffic between client and server.

In response to my recent deferred content loading post, several of you asked how to limit the results, so I added that this time around. The Take extension method performs this task for us.

Calling the page method with jQuery

On the client side, the first thing we need to do is initiate a request to the page method. We’ll do this with jQuery’s ajax() method:

$(document).ready(function() {   $.ajax({     type: "POST",     url: "Default.aspx/GetFeedburnerItems",     // Pass the "Count" parameter, via JSON object.     data: "{'Count':'7'}",     contentType: "application/json; charset=utf-8",     dataType: "json",     success: function(msg) {       BuildTable(msg.d);     }   }); });

When the page loads, this function will perform an AJAX request to our page method, requesting information on the first seven feed items. When the response arrives, a JavaScript function will be called with the response data.

If you are unfamiliar with this jQuery syntax, I have covered it in more detail in two previous posts: Using jQuery to directly call ASP.NET AJAX page methods and Three mistakes to avoid when using jQuery with ASP.NET AJAX.

Building and displaying the table

The page method’s JSON response is going to be similar to this:

[{"Date":"6/5/2008",   "Title":"3 mistakes to avoid when using jQuery with ASP.NET AJAX",   "Link":"http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/",   "Description":"Three common problems that I've seen when using jQuery with ASP.NET AJAX, their underlying causes, and simple solutions to them."},    {"Date":"5/29/2008",   "Title":"Using jQuery to directly call ASP.NET AJAX page methods",   "Link":"http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/",   "Description":"An example of how to use jQuery to call an ASP.NET AJAX page method, without using a ScriptManager."}]

The anonymous type in our LINQ query comes through very nicely. The properties that we designated in the page method become keys in an associative array, making it easy for us to work with the data.

To build a table of this data on the client side, we can loop through each element, construct an HTML string, and then assign that string to a container’s innerHTML property:

function BuildTable(msg) {   var table = '';     for (var post in msg)   {     var row = '';       row += '';     row += '';     row += '';       row += '';       table += row;   }     table += '
DateTitleExcerpt
' + msg[post].Date + '' + msg[post].Title + '' + msg[post].Description + '
'; $('#Container').html(table); }

If you think that code looks ugly, that’s because it is. While it works great, I would not recommend this implementation. It will be difficult for you to maintain, and you’ll hope that anyone else forced to maintain it doesn’t know where you live.

Improving the situation with templating

The reason the former code is so ugly is that the presentation and logic are not separated. Even though this is all on the client side, separation of concerns is still an important goal to keep in mind.

To achieve separation, what we really need is a templating solution. As it turns out, there’s a great jQuery plugin called jTemplates, which is perfect for this application.

Using jTemplates, we can create a simple HTML template like this one:

     {#foreach $T.d as post}          {#/for}   
Date Title Excerpt
{$T.post.Date} {$T.post.Title} {$T.post.Description}

Since we’re focusing on disentanglement, this template belongs separate file. If we embedded in our JavaScript, we’d be taking two steps forward and one step back. In this case, I saved it as RSSTable.tpl.

With the HTML template created, we can use a couple of jTemplates’ methods to apply the template to the container and then render the page method’s return.

function ApplyTemplate(msg) {   // This method loads the HTML template and   //  prepares the container div to accept data.   $('#Container').setTemplateURL('RSSTable.tpl');     // This method applies the JSON array to the    //  container's template and renders it.   $('#Container').processTemplate(msg); }

The rendered result will be identical to the previous, manual method, but the code is much cleaner. At this level of abstraction, I consider this method to be very similar to a client side Repeater.

Conclusion

This is a powerful optimization technique. Identifying overburdened UpdatePanels and replacing them with something like this yields massive performance increases. An order of magnitude isn’t uncommon, in my experience.

One of my sites, WinScrabble.com, was suffering from poor performance due to its primary feature relying on partial postbacks. Because the page was simple and had ViewState disabled, I thought the UpdatePanel would have a relatively minimal impact.

You wouldn’t believe just how wrong I was.

When I removed the UpdatePanel and replaced it with this technique, changing none of the underlying algorithms, requests for 7-8 letter searches ran over 400% faster. I have no doubt that you’ll be able to realize similar improvements in your projects.

In an upcoming post, I’ll go into detail about how to add some client side embellishments: Client side sorting, light-weight paging, and using CSS to improve upon the presentation. So, if you aren’t already subscribed to receive updates via RSS or Email, be sure to do so today.

Try it for yourself: download the source

client-repeater.zip (25kb)

Originally posted at: Encosia.

End Grain Cutting Boards – Project of the Week

This weeks project, or more accurately projects, come from four young skilled craftsmen: (from left to right) Jordon, Joe, Sheldon, and Stephen. The picture was submitted by their shop teacher, Jarred. Now I get quite a few emails from shop teachers who use our videos in their classes, and each and every story warms my heart. But this is the first time someone actually sent a picture. I thought it was so cool and that these guys did such a great job, that I would post it as our Project of the Week. I know I may have presented the end grain cutting board as a “great beginners project”, but those of you who have made one will agree with me that it is by no means easy. Its a testament to Jarred’s teaching ability and the personal skill of each one of the guys that their boards look as good as they do!

Here’s what Jarred had to say:

I teach a shop class in rural Wisconsin, and took the initiative to introduce the boys to The Wood Whisperer (someone younger and cooler than me). I walked them through the cutting board project, but showing them your videos. Every time I fired up the laptop they would in unison say, “Let’s get ready to make a cutting board!” Anyway, here’s a picture of a few of them and their cutting boards: combinations of walnut, maple, and purpleheart. The boys had fun with the project and gave the cutting boards as gifts for Mother’s Day.

How to Consolidate Firefox 3′s Chrome [Screencasts]


Now that you’ve minimized Firefox’s chrome with a few good user styles, it’s time to maximize your surfing area. Just by moving a few small things around you can have all of Firefox’s menu and location bar’s features, but without all the real estate-hogging. Check out a video screencast of how to consolidate Firefox’s chrome after the jump.

Firefox looks like this by default:

After the consolidation, you get this. Notice that Firefox’s top bar takes up a lot less vertical space.

To do this on your copy of Firefox, first, you’ll need to install the Stylish extension and grab a few consolidation user styles, namely, the ones that remove the Edit and Help menus, the Go button and magnifying glass, merge the Stop and Reload buttons, and remove the throbber. Then, you want to reduce the size of your back button, and move the location bar, buttons, and search box to the menu bar, and turn off the Navigation toolbar.

Confused? Here’s a video demonstration of how it’s done:

How do you make Firefox fit your surfing style better? Let us know in the comments.


Make Vista Use Multiple Cores to Speed Boot Time [Windows Vista Tip]

boot_option.jpgWindows Vista tip: The Hackosis blog points out that Windows Vista uses only one CPU to boot itself by default, regardless of whatever dual- or quad-core hardware you’re using. Enabling multi-core boot might save you a bit of time, and the fix is pretty simple. Run msconfig from the Start Search box (or after hitting Win+R), then head to the “Boot” tab, check “Number of processors,” and change the drop-down box to fit your processor. I haven’t tested this myself, but given how long it takes Vista to gear up to running speed on my dual-core box, it probably couldn’t hurt, either. Let us know if you see any gains in the comments.


WP Like Button Plugin by Free WordPress Templates