Ruby

ruby slippers


August 24, 2008 17:15 by joel

I've been spending some time lately digging into Ruby. It's a great language, and although my knowledge is still very young, I really enjoy working with it.

The other day I discovered a little cross-platform GUI framework called Shoes, which was created by why the lucky stiff. The API is really simple, making it easy for somebody new to the language to use it, but still focus on learning Ruby. Much of Shoes will seem very familiar to anyone who has coded for the web. Since it's used for creating desktop apps, and not confined to a browser, there are also some things that are borrowed from that realm. I won't dig too much into the "how's", since as i said, it's not very difficult, and the basics are well documented in a number of places (which I'll link at the bottom of the post).  

I took a bit of time today and hacked out a little paint application. A word of warning: my graphical design skills are basically non-existent, and I wasn't all that interested in digging too deep into that aspect of the framework, anyway, as my goal at the moment is to learn Ruby, not Shoes. Also, the paint program only has a few features at the moment, but it will hopefully grow and improve as my knowledge of Ruby grows.

Here's a quick screenshot, with a few things drawn: 

Basic App Screenshot

This screenshot shoes the options pane opened, with some stuff drawn in the background:

App Screenshot - Highlight Toolbar

If you want to take a look, it's hosted in The Shoebox, which is a collection of user-created Shoes applications. My paint app can be found here, and the shoes framework itself can be downloaded from here.

Finally, a bit of code, just so you can get a taste of what this stuff is like. This is the layout code for the options panel, seen above:

@options = stack :width => "100%" do
# Horizontal options menu  
background "#eeeeee"
flow do 
button("Fill Color", :margin => 5,:width => 100) do
fill ask_color("Pick a Color")
end
button("Stroke Color", :margin => 5,:width => 100) do
stroke ask_color("Pick a Color")
end
stroke_width = edit_line :width => 50,:margin => 5
button("<-- Set Line Width", :width => 150, :margin => 5) do
strokewidth stroke_width.text.to_i
end
end          
end

The stack and flow methods define layout areas, similar to divs and spans. Buttons are... buttons. Actually, I'm not going to go through the code. .. there's not much to it, and the actual application, although it's only 100 lines long, is probably already in dire need of refactoring. That's where the fun is, though! It's a big adventure, and I'm just getting started. I'll keep you posted. Maybe.

Stuff to check out:

Shoes

The ShoeBox - Collection of Shoes apps.

Nobody Knows Shoes (the official manual)



General

A Tumultuous Love Affair


July 13, 2008 11:54 by joel

It's been a ... very long time since I've written anything here. Rather than writing a bunch of boring excuses and explanations, I'm just going to jump right back in.

10 years ago I got my first exposure to Linux, and I fell in love. Almost immediately I shoved Windows behind me and jumped in with both feet. Slackware was my choice, and continued to be for quite a while. As time passed, however, I became less interested in maintaining my computer, and more interested in just using it as a tool. I got lazy, and wanted things to 'Just Work'. I can be moody like that. Eventually I began to drift back into the Windows world. I pretended for a while that I was bridging the gap by having my machine dual-boot. But before long the ext2 partition shrunk to nothing, and Fat32 took over again.

In the years since then, I have drifted back and forth, dabbling in Linux, but never having the commitment to jump right in. Partly this is because I didn't want to try out the more 'user friendly' versions, and instead stuck with Slackware, and then Gentoo. Finally, after buying a new computer, and spending a few months getting frustrated with Vista's memory consumption, I decided to do an experiment. So, yesterday, I downloaded the 64-bit version of Ubuntu Hardy Heron. By the middle of the day I had my system up and running and was working in Visual Studio within a virtual machine. The difference was unbelievable. The whole process didn't take much longer than it would have taken to install Windows and get it set up properly. Long gone are the days of researching every minutiae of your hardware, finding the right modules, editing multiple configuration files, and compiling your kernel before you can even boot a workable system. That flexibility is obviously still there, but choosing Linux no longer requires you to dig that deep. (Now, I realize that my thinking is probably antiquated, and it is likely that it has been this way for a while. I have probably just been too stubborn to try a version of linux that didn't assume you WANTED to do all that configuration on your own.)

Anyway, that's all for today. It's been far too long since I've written anything at all, and although this isn't a technical post, it's something. If you're curious, for virtualization I chose KVM (Kernel-Based Virtual Machine). It is the default choice for Ubuntu, and after some research, I decided that it was a good choice. It's integrated directly with the kernel, and as such runs closer to the hardware than a lot of choices. It is also able to take advantage of your processor's virtualization features. After going through the process, I now sit here unscathed, and I can definitely say that it was a good choice. If you're interested, here are a few links that I found helpful. (searching for information relating to KVM produces a lot of noise, so it can be tough to track down helpful info) 

And finally, a screenshot of my desktop with XP and Visual Studio running:

screenshot



Javascript | Performance

Combine Your JavaScript Files. Now.


March 19, 2008 07:55 by joel

Don't argue, just do it. Then read this post to find out why (Hopefully lots of you will already understand why. That's fine. I won't be insulted if you skip this post.).

This topic came up in one of the presentations at Toronto Code Camp this year. Richard Campbell (.NET Rocks) is a great speaker. Not only is he knowledgable, but he's engaging, as well. He's one of those speakers that makes you feel like you'd still be enjoying his presentation, even if you had accidentally stepped into the wrong seminar and had no idea what he was talking about.

The presentation in question was on the topic of "The Scaling Habits of ASP.NET Applications". He provided a ton of useful information, but for the purpose of this post I'm only going to cover one point, which jumped out at me since I spend most of my time on the client-side of things. To be honest, it was the reaction to his comment that jumped out at me the most. The quizzical looks on a lot of the audience, and the number and variety of questions made me realize that a lot of people working in this industry aren't aware of some of the more basic mechanics of browsers and the internet itself. I'm not criticizing, as it is easy to overlook certain things (I'm confident that I make some dumb mistakes, or overlook obvious things pretty often). It just surprised me.

Before you read any farther, download YSlow. You can no longer claim ignorance if questioned. You need this tool (along with Firebug, but you've already got that, right?!?).

Click on the logo in the information bar, and YSlow will analyze the current page, giving a grade from A to F in a variety of performance areas. Expanding an area will give you a bit more detail on the offending files/components and clicking on any of the headings will open a description of what the particular heading refers to. The first area you are marked on, and the one that this post is concerned with, is "Make fewer HTTP requests". Here is Yahoo's description of the best practices for this area. It makes reference to image maps, CSS Sprites, and combining your JavaScript files. Is it really that important, though? What's the difference between one 200k js file and two 100k files?

The root of this problem lies in the fact that the browser can only handle two requests at the same time (this is adjustable from about:config in firefox, and perhaps also in IE, but it won't do you any good, as the limitation is there for a reason and large explosions WILL occur if you tamper with that value). This causes problems because every time you make a request for a particular file (image, css, js, whatever), there is an inherent "round-trip time" (RTT) which is tacked on to the load time of your page. You can't put servers next-door to every one of your users, so a basic analysis using highschool physics reveals the fact that talking to the server takes time. The value of the RTT is out of your hands (unless we start talking about distributed servers and CDN's, but that's way outside the scope of this post, and the budget of most small to medium-sized projects). It's a constant which you need to take into consideration when developing each and every page in your application.

(I debated whether or not to include an equation in this post. I'm not going to, but If you would like to dig deeper into these performance issues, there is a report which Richard made reference to that goes into much greater detail. Although you can just search for it directly, I don't think I'm supposed to link directly to the report. So if you'd like to register first, for their benefit, head here. The report is centered on issues facing Application Delivery Systems. At the outset, however, there is some excellent information on the performance issues facing any developer. The equation on the third page of the report is of particular relevance.)

Often, when trying to optimize the performance of an application, a developer will spend countless hours on the code itself. As client-side programming has become more prevalent, a lot of attention has been focused on the size of JavaScript files. While it's important not to have superfluous code, spending countless hours refining your code is rarely time well spent. If the application does what it is supposed to, optimize other areas first, then as a last resort you can spend some time tweaking the code.

To illustrate what I am saying, let's consider a small example. Assume that the total size of all files associated with a certain page is 350.5K. Internet connections are getting faster, generally, so I'll just use my connection as an example. According to speedtest.net, my download speed is 6846kb/s. This means that bandwidth accounts for approximately 51ms of the total page load time in this example. Yet the page took 3.627s to load (initial load, no caching). There are a lot of other factors affecting the load time, all of which are included in the equation which I mentioned previously. RTT, however, is the one that this post is concerned with, so let's see how it affects the total time it takes our page to load. When I ping the server, I get an RTT of 102ms. So, with a total of 27 HTTP requests, at 102ms each, taking into account that we can do 2 at a time, we get a total of 1.377s. This means that 38% of our load time is attributable directly and exclusively to the length of time it takes something to get from the client to the server and back again.

Let's go back for a second to the ways that most developers initially try to optimize their page-load time. Optimizing your script files is going to make a bit of a difference. But there's only so much you can do there. You might spend two days optimizing your code and find that you can cut a few Kb off the filesize and 30 to 40 milliseconds off the time it takes the browser to parse the page. If you've done a good job writing your code, that much of a savings might not even be realistic. We'll use it as an example anyway. You've just spent two days and managed to pull off a 1% savings on initial load time. "Not too bad" you say as you pat yourself on the back.

Now let's pretend that you left your computer on and your 10 year-old, just learning the intricacies of notepad and figuring he'd give you a hand, cut and pasted all of your 8 JavaScript files into the same file. When you discover what has happened, you panic, but decide to load the page anyway, just to see what happens. To your surprise, the page still works, and it loads in 3.27s. This means that in 15 action-packed minutes, your 10 year-old managed to cut 357ms from the load time: somewhere in the vicinity of 10 times better than you were able to do in two days of work.

That was obviously a very simplified example. If you check out the resource that I mentioned (mainly the various components of the equation), you'll realize that there are many more factors involved in the time it takes to load the page. The load times I mentioned, and the savings I mentioned, however, are very real. You won't have to look very far to find web pages that pull in eight or more JavaScript files. Cutting their size, using a utility such as Yahoo Compressor, and gzipping them are all important optimizations that you should be doing already. When you combine that with a reduction in the number of requests you are making you will have achieved the biggest performance boost that your page can get, without adjusting a single line of code. When you begin to dig deeper than that, the solutions will continue to get more difficult, more expensive, and will provide you with smaller performance enhancements.

What I hope you take away from this post: Do the cheap and easy optimizations first, and the expensive and time consuming options may not even be necessary.



Javascript

Instantiating Server-Side Objects From the Client Using ASP.NET AJAX


March 3, 2008 08:40 by joel

The topic for this post grew out of a number of conversations I've had in recent weeks on subjects relating to WebMethods. For the purposes of this post, I'm going to focus on the the more specific subject of instantiating server-side objects from the client. Although it is a relatively simple thing to accomplish, I think it provides something very tangible and useful to use a starting point for understanding the different ways that the ASP.NET AJAX framework simplifies the exchange of data between the client and the server. 

To begin, I'm going to fire up Visual Studio and create a new ASP.NET 3.5 website (note, however, that everything I am going to do in this post works pretty much the same in ASP.NET 2.0 with the AJAX framework installed). The first step is to define the class which we want to instantiate from the client. Let's use a person as an example. We'll give the class Name, Age, and Weight properties :

Class Screen Shot

Note that I've used a shortcut provided by C#3.0. If your getter and setter don't require any additional logic, you can simply declare your properties as I did for this class. It is just a shortcut provided by the compiler, and the underlying CIL will be exactly the same as if you had defined the properties in the old way, using private variables and getter/setter methods.

The next step is to create a WebService. To keep things simple, the WebMethod will take a Person object as an argument and will return a string.

WebService

The cool thing about this is that since the method takes a Person as an argument, once you register the WebService with the ScriptManager, the client will automatically have a definition of Person. In fact, with VS2008, you'll even get intellisense for it. So for this example, instantiating a Person on the client is as simple as creating a new object, like so:   

the js

All I'm going to do to demonstrate this is call the HelloWorld method, passing it the Person object which I created. In the callback function, I'll simply pass the returned string to an alert: 

the demo

If you try this out, you'll see that as you might expect, you get an alert which says "Hello Bob". So what exactly is going on?

One of the goals of the ASP.NET AJAX Framework is to bridge the gap between the client and the server. In practice, this means that a developer can use a combination of server-side and client-side logic to solve a problem. It does this in a number of ways, including automatically serializing and de-serializing the data on both the client and the server. I won't get into great detail here, as I don't think it's profitable for this discussion. If, however, you'd like a more thorough explanation of what is going on behind the scenes, take a look here. To help you understand what happened in this specific example, we'll take a quick peek behind the scenes using firebug:

firebug

What you are looking at is an automatically generated script file. Most of the file is made up of a JavaScript proxy object which does the work of enabling access to the WebService. The last few lines that I've circled create a definition of a Person object on the client, which is then associated with the server-side Person class. It does this by generating a typed constructor, which basically just means that each Person object that you create will have a __type property, containing the name of the class. Because of that definition, you can both pass a Person to the server as an argument to a WebMethod, or return a Person back to the client, and it will be recognized in both instances. Another cool thing that you'll discover if you dig a bit deeper is that you can also pass collections back and forth. For example, an array or a generic list of Person objects will also be recognized on both the client and server. 

Before I finish, I'll mention one more scenario. If you happen to have a class on the server that you aren't necessarily using in any of your WebMethods, but you want to be able to instantiate and use it on the client, you can add the GenerateScriptType attribute to your WebService. Assuming that I've created another class, called Pet, here is the new WebService:

new webservice

With that attribute set, it is now possible to create a new Pet object in JavaScript, on the client. One thing to remember, as you begin passing objects back and forth between the client and server, is that JavaScript is a dynamic language. The immediately obvious consequence of that fact is that you can add new properties to a JavaScript object at any time. So although the server-side Person may only have Name, Age, and Weight, it is technically possible to add new properties to your client-side Person at any time during program execution. The consequence of this could be lost data. If, for example, you were to add a ShoeSize property to your client object, and then pass the Person as an argument to a WebMethod, there won't be any error. The Person on the server will simply be populated with the Name, Age, and Weight, but the ShoeSize data will be thrown away.

And finally I'll mention something that came up during a conversation I had at Toronto Code Camp on this topic. During the conversation, we were wondering whether or not the generated constructor contains definitions for the properties of the server-side object. I looked into it yesterday and discovered that it does not. In practice, this doesn't actually matter, however. Being a dynamic language, the following two snippets of code in JavaScript produce exactly the same result:

Example 1

function Person() {
this.Age = null;
this.Name = null;
}
var Bob = new Person();
Bob.Name = "Bob";
Bob.Age = 35;

Example 2

function Person() {}
var Bob = new Person();
Bob.Name = "Bob";
Bob.Age = 35;

Basically the only real downside of the constructor not getting pre-populated with the correct properties is that you don't get intellisense for your client-side objects until you begin to assign them properties. Since JavaScript intellisense is a very new thing in Visual Studio, anyway, probably this is a problem I can overlook for the moment. :)



Javascript

Client-Side Controls With the Microsoft AJAX Library


February 22, 2008 08:42 by joel

Introduction

The purpose of this post is to explain how to build a client control using the Microsoft AJAX Library. This is cool because it lays the foundation for building extenders and script controls. If you've been working at all with ASP.NET AJAX, you'll definitely know what an extender is, as they are the simplest way to add AJAX functionality to a page using the ASP.NET framework. A script control is also an AJAX enabled control, but it doesn't rely on external components. It is a fully contained, AJAX enabled server control. I'm getting ahead of myself, though, and I'll save that topic for another post.

My post today is going to focus on the client-side, where my passion really lies. The control that I'm going to walk you through was created for a specific purpose: to provide a dynamic container which displays thumbnail images, allowing a single image to be selected at any given time. You could say that it acts as a sort of thumbnail menu. You can download the source for the control here.

Before I get into actually building the control, I'll lay out the list of requirements that I started out with:

  • The control needed to be dynamic. There had to be functionality for adding or removing images at any time.
  • There had to be a means for providing visual feedback when an image was hovered over, or selected.
  • There needed to be an external event which fired when an image was selected.
  • The control needed to always be aware of which image was selected.

Classes in the Microsoft AJAX Library 

A control in its most basic form is just a class, defined with the Microsoft AJAX Library, which inherits from Sys.UI.Control. Although there are some differences building a simple class with the library is very similar to doing it with straight-up JavaScript. You first define a constructor function, which contains the properties and their inital values, and you define the prototype object, which typically contains the methods of the class. The main differences are outside of the actual class definition, and lie in the two registration methods. The first is used if you want the class to reside in a namespace. The Type.registerNamespace method is used to define the namespace, and needs to be called before the class definition. Using a namespace is not required (it is, however, highly recommended). The second is the registerClass method, which is called after the class is defined. The only required argument for the method is the fully-qualified name of the class. As a brief example, here is an empty class, defined using the Microsoft AJAX Library:

Type.registerNamespace('Example');
Example.SampleClass = function() {
    // Class Properties
}
Example.SampleClass.prototype = {
    // Class methods.
}
Example.SampleClass.registerClass('Example.SampleClass');

A Control 'Skeleton' 

That is all that is needed to create a simple class. As I said earlier, a control is actually just a class that inherits from Sys.UI.Control. Because controls utilize class inheritance based within the Microsoft library, there are a few specific things that need to be implemented in your control class. Here is the skeleton of the ImageSelectorDiv control:

Type.registerNamespace('PhotoLoc');
PhotoLoc.ImageSelectorDiv = function(element) {
    PhotoLoc.ImageSelectorDiv.initializeBase(this, [element]);
    // Properties removed for simplicity.
}
PhotoLoc.ImageSelectorDiv.prototype =  {
    initialize : function() {
        PhotoLoc.ImageSelectorDiv.callBaseMethod(this, 'initialize');
        // The initialize method is inherited from Sys.UI.Control 
        // and is typically overridden in each inheriting class
        // to provide functionality when the class is initialized.
        // The callBaseMethod() method does precisely what it says. .. 
        // It calls the initialize method of the inherited class.
    },
    dispose : function() {
        // This method is called, just as the control is being disposed, 
        // allowing you to clean up event handlers, or anything else.
        PhotoLoc.ImageSelectorDiv.callBaseMethod(this, 'dispose');
    }
    // The remainder of the class methods are defined here. 
}
PhotoLoc.ImageSelectorDiv.registerClass('PhotoLoc.ImageSelectorDiv', Sys.UI.Control); 

The first thing you'll notice is the initializeBase method which is called from the constructor. This method, along with the two callBaseMethod methods are required in order to inherit the properties and methods of the base class. It is through those methods that the library implements class inheritence.

The initialize and dispose methods are provided by the base class, and are generally overridden, as I did in this control. They allow logic to be called when the class is initialized and right before it is disposed. Typically they are used to do things like add event handlers and initialize properties in the initialize method, and remove event handlers in the dispose method (preventing memory leaks). The other thing you'll notice is that the constructor accepts an argument which I've fittingly called element. The reason for this is that each client control is associated with a DOM element. When you create an instance of the control, you need to pass the element into the $create method (which in turn passes it to the class constructor), or there will be an error at runtime.

Control Properties 

Accessor(getter) and mutator(setter) methods are used in a similar way to properties in a language like C#. Although there is no way to declare a variable as private in JavaScript (it is technically possible to create variables that aren't accessible from outside an object, but that's a topic for another time), a common practice that is used to signify a private variable is adding an underscore to the front of its name. You will notice that all of the properties in the constructor are preceded by an underscore. When you use this technique, the framework recognizes the property as private and automatically uses the accessor or mutator methods to access that property. For example, consider the _selectedCssClass property of the control. The accessor and mutator methods for that property are:

get_selectedCssClass : function() {
    return this._selectedCssClass;
},
set_selectedCssClass : function(value) {
    this._selectedCssClass = value;
},

For every instance of the control that is created, you can set the _selectedCssClass property by passing the following object literal into the $create statement:

    { 'selectedCssClass' : 'yourCustomCssClassName' } 

Any properties that you have exposed using accessors and mutators can be set in that way.

Creating the Control in your Page 

I have laid out the basics of a control, so I'll quickly explain how to add it to the page before I fill in the details of this specific control. The method which accomplishes that is the $create statement (the $create statement is a shortcut for calling the Sys.Application.create method), and it is called during the init stage of the client page lifecycle. In my specific application, the $create statement for this control looks like this:

$create(PhotoLoc.ImageSelectorDiv, {
    'unselectedCssClass' : 'imageBoxHover',
    'selectedCssClass' : 'selected',
    'imageSelectedHandler' : imageSelected
}, 
{}, 
{},
$get('PhotoContainerInner'));

The first argument is the fully qualified name of the control. The second argument is the object literal in which you define the client properties. Notice that I have set two CSS classes: one for the unselected images, and one for the selected image. Although it looks like an ordinary object literal, the second object is actually a JSON object. For that reason, the name of the property is always passed as a string. You will also notice that it doesn't have the preceding underscore. The value of the property needs to be one of the accepted JSON values. These properties satisfy two of the requirements that I laid out at the beginning. The two CSS classes are used to provide a means for setting the visual style of the selected and unselected elements. The 'imageSelectedHandler' contains the name of a function which is used as an event handler for the 'imageSelected' event that is raised by the control whenever a new image is selected.

The third and fourth argument I won't talk about here, since they aren't used in this example, but you can find out more about them here. The final argument is a reference to the DOM element that the control will 'wrap', or be associated with. In this case it is a div, with an id of 'PhotoContainerInner'.

As I said, the $create statement is called during the init stage of the client page lifecycle. This event is accessed through the Sys.Application class. The following code adds a handler, onInit, for the page init event:

Sys.Application.add_init(onInit);

The $create statement would then be called from the onInit function, which would in turn create the control on the page. 

Public Methods

One of the requirements for this control was that it needed to provide a means for adding and removing images. This is implemented using public methods. You'll notice that the following method names aren't preceded by an underscore, meaning that they are intended to be public methods.

// Public Methods
addImage : function(image) {
    $addHandler(image, 'click', this._clickHandler);
    if(!image.id) {
        this._imageCounter++;
        image.id = "image" + this._imageCounter;
    }
    this._imageCollection[image.id] = image;
    this.get_element().appendChild(image);
    Sys.UI.DomElement.addCssClass(image, this._hoverCssClass);
},
    
removeSelectedImage : function() {
    this.get_element().removeChild(this._selectedImage);
    delete this._imageCollection[this._selectedImage.id];
    this._selectedImage = null;    
},
    
removeImage : function(image) {
    if(this._selectedImage == image) {
        this.removeSelectedImage();
    } else {
        this.get_element().removeChild(image);
        delete this._imageCollection[image.id];
    };       
},
clearImages : function() {
    this._imageCounter = 0;
    this._selectedImage = null;
    for(var image in this._imageCollection){
        this.get_element().removeChild(this._imageCollection[image]);
        delete this._imageCollection[image];
    };
},
getSelected : function() {
    return this._selectedImage;
},    
  

The question that I will now answer is "how do I access the control from my code?". That is an excellent question, as public methods aren't much good if you don't know where to find them. In short, the answer lies with the $find shortcut, provided by the library. It works just like the $get shortcut, except that it returns the control object, rather than a DOM element. Even though it returns the control, you still pass it the id of the associated DOM element. For my example, I would call the addImage method in the following way:

$find('PhotoContainerInner').addImage(pic); 

Details

You now know how to define and implement a custom client-side control. There are a few other concepts that I'll quickly cover before I finish. These won't be applicable in every control, but they are used here, and will be helpful in a lot of situations.

Looking at the class, you may have noticed the _clickHandler property. This property is used as a delegate to handle the internal click event. This is an implementation of another aspect of the Microsoft AJAX Library which will be familiar to anyone from a .NET background. The basic purpose of a delegate is to invoke a function which is used as an event handler. The reason this is useful has to do with scope. Generally, within an event handler, this refers to the element that hooked up the event. That is often not the behavior that you want. When building a class, it is often useful to have this continue to refer to the instantiated object. You can accomplish this by passing a delegate as the event handler, instead of a simple function.

A delegate is created using the Function.createDelegate method. The method accepts 2 arguments and returns a function. The first argument is the object that you wish to refer to as this within the event handler. The second argument is the function which will handle the event. So for this control, here is the delegate and the event handler function:

// Event Handler
_onImageClick : function(e) {
    if(e.target != this._selectedImage) { 
        if(this._selectedImage) {
            Sys.UI.DomElement.removeCssClass(this._selectedImage, this._selectedCssClass);
            Sys.UI.DomElement.addCssClass(this._selectedImage, this._hoverCssClass);
        };
        this._selectedImage = e.target;
        Sys.UI.DomElement.removeCssClass(this._selectedImage, this._hoverCssClass);
        Sys.UI.DomElement.addCssClass(this._selectedImage, this._selectedCssClass);
        this._raiseEvent('imageSelected', { event : e, image : this._selectedImage });
    };
},
// Delegate
_initializeClickHandler : function() {
    this._clickHandler = Function.createDelegate(this, this._onImageClick);
}, 

This allows us to handle the event with the the _onImageClick function, by way of the delegate, but still refer to the control object as this.

Another thing I'll mention is custom events. The third requirement that I had for the control is that it needed to provide an external event which fired whenever an image was selected. To accomplish that task I used the custom event functionality within the Microsoft AJAX Library to create an event called 'imageSelected' which is exposed through the control. Every component that inherits from Sys.Component (controls and behaviors both inherit from Sys.Component) has the ability to raise custom events. As that is a topic for an entire post, however, I'll just point you in the direction of somebody that has already explained it very well

The Finish Line

Building a client control, I realized mid-way through this article, is a subject that can't be thoroughly covered in such a short space. However, I hope that  the article, combined with the code, will give you a pretty good picture of what it takes to build a custom control. I created the control for use in a little side-project that I'm working on, so once it is live I will post the link here so you can see the control in action. Hopefully over the next little while I'll also do some posts which build on this topic and explain the process of creating custom extenders and script controls (I will, however, split them up into a series, rather than trying to tackle a whole topic in a single post, which will hopefully do it a bit more justice than I did this topic).

The following image is a screenshot of the control in a partially implemented state. The selected image has a thick green border, and the alert was called from the 'imageSelected' event handler:

screen shot image



Javascript | Pros and Cons

// TODO: AJAX Library Reviews


February 21, 2008 10:59 by joel

I've been mulling over a series of posts on various AJAX libraries. Part of the reason they have not yet materialized is because it's so difficult to figure out what I think about each of them. One second I'll be disgusted with the way that a library has implemented something, and the next second I'll be raving about its awesome features on twitter or some other outlet. The fact is, every library is created with a specific goal in mind. Because of that, there are naturally going to be things that they each do well, and also things that they don't do well. Which brings me back to my original thought: a series of posts about the relative merits and demerits of various libraries. To be honest, I'm not sure if that specific series will ever appear. However, I will try to include some comparisons as I cover various ways of tackling problems in different libraries. I'm going to try something, which I'm not sure will work, but i'm going to try it anyway: whenever I consider a post to highlight a pro or a con of a particular library, I'll throw it in the 'Pros and Cons' category. That way it'll be easier to filter out those posts and find what you're looking for. Perhaps at various intervals, I'll pull together some of those posts, as well as some external posts and do a 'Review Collection' on a particular library.

So now I suppose you're ticked off that I forced you to read this lame post, and didn't give you anything to take away... Well, quiver with excitement, and keep checking back, because your 'take aways' will come.  



Javascript | Book Review

Book Review: ASP.NET AJAX In Action


February 17, 2008 18:08 by joel

I love to read. It's safe to say that one of my favorite activities is sitting down with a good book. Maybe it's just the type of learner that I am, but In terms of professional development, I also think that reading is one of the most important activities that I undertake. Getting your hands dirty, hacking out solutions to problems on your own is something we've probably all experienced. The truth is, though, that for mortals like myself, it's just not the best way to tackle most problems. Generally there is somebody that has already encountered most of the problems that I'm going to face. Even if they haven't dealt with the specific issue I'm facing, more often than not somebody has written something about the underlying technology that will better help me attack the problem. 

I hope to add a section on my website in the future where I will post reviews of books that I've read. After all, a good book can be a great help, but taking the time to read a bad book can be extremely frustrating.  Not that you should implicitly trust my judgement, but it's a lot easier to read a few reviews of a bad book than it is to waste time ploughing through it, only to discover it wasn't worth the read.

So there's my introduction. Now on to the review:

ASP.NET AJAX In Action is an excellent read. While the book is definitely not for the beginner, if you already have a grasp of both JavaScript and ASP.NET, it is a great eye-opener to the powerful features of the ASP.NET AJAX Framework. You definitely don't need to be a JavaScript expert to appreciate it, as the authors do give a rundown on the language, but I think having some understanding ahead of time is a good idea.

The book is only 538 pages (right to the back. index and all.) and is a pleasant reminder that a book does not need to weigh as much as an automobile to be effective. It is concise in its descriptions, especially in the earlier stages, meaning that you need to pay attention to keep from missing vital information, but it is also extremely thorough. I should point out, also, that while it does move quickly, it isn't difficult to understand. 

A lot of computer books that focus on a specific technology can suffer from irrelevance and outdated material before they are even published. This book does not have that ailment in very many places at all. The authors clearly had a very thorough understanding of the technology as it was being developed, and they chose their material well.

I think one of my favorite aspects of the book is that it doesn't cater to developers that just want an easy "plug and play" solution to a problem. If you just want to know how to make your FileUpload control work with your UpdatePanel, this is definitely not the book for you. Instead, the authors provide a strong base, giving you the understanding you will need to really take advantage of the framework. You will learn how to leverage the Microsoft AJAX Libraries in your client-side development, and you will also learn a server-centric model for developing against the framework. One of the great advantages of ASP.NET AJAX is that flexibility. There is a lot of freedom to develop in the "realm" that you feel most comfortable with, whether that be with JavaScript or a .NET language. In addition, if you're primarily a JavaScript developer, the framework opens giant doors of opportunity to utilize some of the more powerful aspects of server-side development without straying too far out of your comfort zone. I'll write a few posts about some of those techniques in coming days.

As a summary, I'll just say that if you're looking for a book on ASP.NET AJAX, you don't need to look any farther than this one. 



Javascript

Mouse position - relative to a containing element


February 5, 2008 19:06 by joel

There is something about browser quirks that brings to mind a schoolyard argument. Both sides punching and kicking their way around a meaningless dispute, simply because they're both too stubborn to get along. It may be immature, but it's unfortunately the situation that every JavaScript programmer currently finds themselves in.

I've been doing some work lately with the new MapQuest JavaScript API, which will be officially launched sometime in the next few weeks. The other day I stumbled across a problem that in some situations has a relatively simple solution, but nonetheless seems to be quite difficult to accomplish: discovering the coordinates of a mouse event relative to the containing element.

I'm not going to get into the relative merits and de-merits of the Microsoft AJAX Library. I'll save that for another post. However, since I work with ASP.NET, and the library is automatically included with an ASP.NET AJAX website, I have gotten used to some of the shortcuts that the library provides. Now, I'm sure that there are some JavaScript libraries out there that provide a method for discovering these ellusive coordinates, regardless of the browser or the immediate situation. Unfortunately the Microsoft Library doesn't seem to be one of them. Theoretically, the event.offsetX and event.offsetY values should give you these coordinates. Practically, however, it just doesn't work in a consistent way. This is the solution that I came up with for my problem, and it seems to work fairly well in a lot more situations than just pulling the offset values out of the event object.

function Position(e,ele){
// gotta pull 2 pixels out of the mix in IE, for some reason
var offset = (Sys.Browser.agent == Sys.Browser.InternetExplorer) ? 2 : 0; 
var deShort = document.documentElement;
var lefty = (deShort.scrollLeft ? deShort.scrollLeft : document.body.scrollLeft);
var toppy = (deShort.scrollTop ? deShort.scrollTop : document.body.scrollTop);
var loc = Sys.UI.DomElement.getLocation(ele);
return { y  : e.clientY + toppy - loc.y - offset,  x : e.clientX + lefty - loc.x - offset }
}

So basically all you do is pass your event object and the containing element into this function, and it should return you an object with x and y coordinates, relative to the top left corner of that element. Will I be surprised if you give me a situation that this doesn't work in?? Not at all. Feel free to let me know, though, and I'll try and update with a fix, as the need arises.



Javascript | General | scripts

Installing A Greasemonkey Script


January 29, 2008 16:35 by joel

My last post was written as an introduction to the Greasemonkey API from Gmail. Its intent was to introduce wouldbe greasemonkey scripters to the various methods that are available in the API. It has recently come to my attention, however, that not everybody is interested in writing their own scripts. Perhaps, in fact, I am a member of the minority.  *gasp*

So. This post will be a simple rundown on how to install my Ad-Removing script, for those that aren't interested in how it works:

1- Get Firefox.

2- Install the Greasemonkey Add-On.

3- If you are using Gmail, install this script.  If you are using Google Apps, install this script.

4- Refresh Gmail/Google Apps.

And that's all there is to it. Lately there have been periodic changes in the way Gmail sets up their pages. I'm usually pretty quick to update the script, so if something starts looking weird, come back here, or head over to userscripts.org (links to follow) and re-install the script.

As a sidenote, while you're at userscripts.org check out some of the other scripts that are available from other users. There is a huge quantity of scripts there that do a lot of helpful things, and once you have Greasemonkey installed, it is a simple thing to add new scripts. Just do a search for the page that you're interested in modifying, or the action you want it to do (ie: remove facebook ads), and likely somebody has written a script for that purpose. Just be careful, as the big red banner at the top of every script page says, if you're installing a script that is new. I would go as far as to say that if you're not familiar with scripting, you shouldn't install a script if less than a couple hundred people have installed it. Also check out the comments to see what other users have said about it. And that's a wrap, as they say. Enjoy my script, and check out some others while you are at it. 

My pages on userscripts.org:

The Gmail Script

The Google Apps Script